ZUREE API
EN PT-BR ES
Book a technical demo
Clinical document intelligence API · V1

Medical paperwork in. Structured clinical data out.

Claims teams and telemedicine platforms lose weeks to lab PDFs, scanned prescriptions and faxed clinical summaries. Zuree reads them and returns normalized, LOINC-coded facts — each one carrying a confidence score and provenance back to the exact source document.

One REST API. Idempotent uploads, signed webhooks, a typed TypeScript SDK, and a FHIR R4 representation of everything it extracts.

Document types
Lab reports · Prescriptions · Clinical summaries
Every fact returns with
Coding · Confidence · Provenance
POST /v1/documents/:id/process
Response · 202 Accepted
{ "jobId": "job_8Kd2", "status": "QUEUED" }
Webhook · document.processing_completed
{
  "type": "document.processing_completed",
  "data": {
    "documentId": "doc_3Fq9",
    "documentType": "LAB_REPORT",
    "processingStatus": "PROCESSED"
  }
}
GET /v1/patients/:id/observations
{
  "display": "Hemoglobin",
  "coding": { "system": "LOINC", "code": "718-7" },
  "valueNumeric": 13.5, "unit": "g/dL",
  "interpretation": "LOW",
  "confidence": 0.93,
  "provenance": { "documentId": "doc_3Fq9",
                  "method": "AI_TEXT" }
}
01 · The problem

Clinical history arrives as documents, not as data.

A single claim or intake can involve a dozen files from a dozen labs, each with its own layout, units and abbreviations. Someone has to read them.

Manual abstraction doesn't scale

Nurse reviewers and claims adjusters retype values into forms. Throughput is capped by headcount, and the cost per file never falls.

Raw OCR isn't an answer

A text dump still needs classifying, coding and unit normalization before a rules engine or model can use it.

Unsourced extraction is unusable

If a reviewer can't trace a value back to the page it came from, it can't support a decision that has to be defended.

Building it in-house is a detour

OCR, template detection, prompt versioning, schema validation, idempotent retries, audit trails. Months of work that isn't your product.

02 · How it works

Ten checkpointed stages, in a fixed order.

Every stage is idempotent and checkpointed per document. A retry resumes where it stopped — it never duplicates work or re-bills an AI call for a stage that already completed.

Stage 01 of 10

Ingestion

The file lands in private object storage keyed by tenant plus a SHA-256 of its bytes. That hash is the document’s identity, so an identical re-upload resolves to the existing document instead of creating a second one.

What the ledger records
stage: INGESTION
status: ok  ·  42ms
sha256: 9f2c…a71b
dedupe: miss

Every processing run is auditable: a stage ledger with timings, tokens, cost and escalation decisions. AI output is treated as untrusted input — it passes schema validation before anything downstream reads it, and repaired JSON is flagged as repaired, never returned as clean.

03 · Before and after

Click a line on the report. See the fact it becomes.

Provenance is not a footnote — it is a field. Every extracted fact points back to the document, the extraction record, and the method that produced it.

Input · lab-report.pdf 2.1 MB
MERIDIAN CLINICAL LABORATORIES
Specimen 88-41207 · Collected 2026-07-01
ANALYTERESULTUNITREF RANGE
Reviewed by C. Okafor, MD · page 1 of 2
Output · observation LOW
{
  "display": "Hemoglobin",
  "coding": {
    "system": "LOINC",
    "code": "718-7",
    "display": "Hemoglobin"
  },
  "valueNumeric": 13.5,
  "unit": "g/dL",
  "referenceRange": {
    "low": 12, "high": 16, "unit": "g/dL",
    "text": "12.0 - 16.0"
  },
  "interpretation": "LOW",
  "observedAt": "2026-07-01",
  "confidence": 0.93,
  "provenance": {
    "documentId": "doc_3Fq9",
    "extractionId": "ext_7Bm2",
    "method": "AI_TEXT",
    "confidence": 0.93
  }
}
04 · Quickstart

Five calls from zero to structured data.

POST /v1/patients
curl -sX POST "$ZUREE_BASE_URL/v1/patients" \
  -H "Authorization: Bearer $ZUREE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pseudonym":"ext-user-42"}'

# → {"id":"<patientId>",
#     "pseudonym":"ext-user-42",
#     "createdAt":"2026-07-01T09:12:04.000Z"}
SDK @zuree/sdk · create a patient
import { ZureeClient } from '@zuree/sdk';

const zuree = new ZureeClient({
  apiKey: process.env.ZUREE_API_KEY!,
  baseUrl: process.env.ZUREE_BASE_URL!,
});

const patient = await zuree.patients.create({
  pseudonym: 'ext-user-42',
});
POST /v1/documents
CONTENT=$(base64 -i lab-report.pdf)

curl -sX POST "$ZUREE_BASE_URL/v1/documents" \
  -H "Authorization: Bearer $ZUREE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d "{\"patientId\":\"$PATIENT_ID\",
       \"filename\":\"lab-report.pdf\",
       \"mimeType\":\"application/pdf\",
       \"content\":\"$CONTENT\"}"

# → {"document":{"id":"<documentId>",
#                "status":"SECURITY_CHECKED"},
#     "duplicate":false}
SDK @zuree/sdk · upload a document
import { readFile } from 'node:fs/promises';
import { randomUUID } from 'node:crypto';

const bytes = await readFile('lab-report.pdf');

const { document } = await zuree.documents.create(
  {
    patientId: patient.id,
    filename: 'lab-report.pdf',
    mimeType: 'application/pdf',
    content: bytes.toString('base64'),
  },
  { idempotencyKey: randomUUID() },
);
POST /v1/documents/:id/process
curl -sX POST \
  "$ZUREE_BASE_URL/v1/documents/$DOCUMENT_ID/process" \
  -H "Authorization: Bearer $ZUREE_API_KEY"

# → 202 {"jobId":"<jobId>",
#          "status":"QUEUED",
#          "attempts":0}
SDK @zuree/sdk · queue processing
await zuree.documents.process(document.id);

let s = await zuree.documents.status(document.id);
while (s.status === 'PROCESSING') {
  await new Promise((r) => setTimeout(r, 2000));
  s = await zuree.documents.status(document.id);
}
POST /v1/webhooks
curl -sX POST "$ZUREE_BASE_URL/v1/webhooks" \
  -H "Authorization: Bearer $ZUREE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-app.example/hooks/zuree",
       "events":["document.processing_completed",
                 "document.processing_failed"]}'

# → {"id":"whe_…","secret":"whsec_…"}
SDK @zuree/sdk · react to the webhook
import { verifyWebhookSignature } from '@zuree/sdk';

app.post('/hooks/zuree', async (req, res) => {
  const raw = await readRawBody(req);
  const check = verifyWebhookSignature({
    payload: raw,
    signatureHeader: req.headers['zuree-webhook-signature'],
    secret: process.env.ZUREE_WEBHOOK_SECRET!,
  });
  if (!check.ok) return res.status(401).end();

  const event = JSON.parse(raw);
  res.status(200).end();
});
GET /v1/patients/:id/observations
curl -s \
  "$ZUREE_BASE_URL/v1/patients/$PID/observations?limit=50" \
  -H "Authorization: Bearer $ZUREE_API_KEY"

# → { "items": [ { "display": "Hemoglobin",
#       "coding": {"system":"LOINC","code":"718-7"},
#       "valueNumeric": 13.5, "unit": "g/dL",
#       "interpretation": "LOW", "confidence": 0.93,
#       "provenance": {…} } ],
#     "nextCursor": "b2Zmc2V0OjUw" }
SDK @zuree/sdk · read the clinical facts
for await (const obs of zuree.clinical.observationsAll(patient.id)) {
  console.log(
    obs.display,
    obs.valueNumeric ?? obs.valueText,
    obs.unit ?? '',
    `(${obs.confidence})`,
  );
}

for await (const e of zuree.clinical.timelineAll(patient.id)) {
  console.log(e.date ?? '(undated)', e.kind);
}

Idempotent by design

Send an Idempotency-Key and a retry can’t duplicate. Identical bytes dedupe automatically.

Signed webhooks

HMAC-signed, at-least-once delivery with exponential backoff and a per-endpoint delivery log.

Rate limits you can code against

429 with Retry-After. The SDK retries automatically, honoring it.

OpenAPI + FHIR R4

Live spec at /v1/openapi.json. Clinical data also exports as FHIR R4.

05 · Who it's for

Four industries, one bottleneck.

Insurance & claims

Adjudicate on data, not on attachments

Feed claim attachments straight into your rules engine. Coded observations, medications and procedures arrive with confidence scores, so you can auto-approve the clean ones and route only the ambiguous files to a human.

  • Confidence thresholds drive straight-through vs. manual review
  • Provenance on every field for defensible decisions and appeals
  • Append-only audit log of exports, deletions and data access
Telemedicine platforms

The clinician sees history, not a stack of PDFs

Let patients upload whatever they have during intake. Zuree returns a merged chronological timeline — labs, medications, conditions, procedures, encounters — so the consult starts with context instead of a document viewer.

  • Merged /timeline endpoint, chronological across fact types
  • Async pipeline plus webhooks — intake never blocks on parsing
  • Trend-ready values: numeric, unit-normalized, reference ranges intact
Health insurers

Underwriting inputs that are actually comparable

Medical evidence from a hundred different labs normalizes to the same coded model, so risk scoring compares like with like. LOINC where a code exists, an explicit Zuree LOCAL code where it doesn’t — never a silent guess.

  • Unit and reference-range normalization across sources
  • Portable per-patient JSON export, plus FHIR R4
  • Configurable per-tenant retention windows
Health-tech startups

Ship the feature, skip the pipeline

You could build OCR, template detection, prompt versioning, schema validation and an audit trail. Or you could install the SDK this afternoon and spend the quarter on the product your users actually asked for.

  • Typed @zuree/sdk with auto-pagination and retry built in
  • Pseudonymous patients — no real identifier required to process
  • Start on the lowest tier and grow into volume pricing
06 · First-party proof

We shipped a consumer app on this API before selling it.

Zuree Mobile is a live consumer product running entirely on the endpoints documented on this page — the same pseudonymous patient model, the same ten-stage pipeline, the same coded output. No private endpoints, no privileged path.

That makes it our reference implementation and our standing accuracy benchmark: unfamiliar lab layouts hit it every day, and a regression surfaces in real records before it can reach a customer’s tenant.

  • Exactly the /documents → /process → /timeline path shown in the quickstart
  • Consumer-scale volume across lab templates nobody onboarded in advance
  • Its summaries and coaching sit above the API — the API itself still only transcribes
zuree.app · every upload becomes a record
zuree.app · every upload becomes a record
zuree.app · confidence, plus a link to the source document
zuree.app · confidence, plus a link to the source document
Same API, one layer down
zuree.app  (iOS / Android)
   │
   └─ POST /v1/documents
      POST /v1/documents/:id/process
      GET  /v1/patients/:id/timeline
         │
         └─ the same V1 API on this page
07 · Privacy & security

Built for pseudonymity, not retrofitted for it.

You identify patients with an opaque reference you control. Zuree never needs a real-world identifier to process a document.

What we don't claim

Zuree makes no regulatory compliance claim — not GDPR, not HIPAA, not any other framework. The controls beside this are the technical mechanisms we implement and will walk your security team through. Determining lawful bases, retention periods and erasure obligations in your jurisdiction remains yours. We’d rather tell you that up front than in diligence.

No clinical content in telemetry

Logs, metrics, analytics, error trackers, webhook payloads and audit records carry opaque IDs, codes and counts — never document content.

Tenant isolation on every query

Tenant identity resolves server-side from your API key. A tenant_id is never accepted from a request body.

Private storage, short-lived URLs

Object storage buckets are private; signed URLs expire in minutes. Uploads are malware-scanned and content type is verified from the bytes.

AI provider transparency

Every extraction records which provider, which exact model, which prompt version and which pipeline version produced it — readable via the API.

Coordinated deletion

Deleting a document clears it from the database, object storage, processing queue and temporary files — leaving an audit record of IDs and counts, not content.

Retention on your terms

Indefinite by default — Zuree never deletes what you didn’t ask it to. Enable a per-tenant document-age window and expired files purge through the same path.

Scope discipline is part of the security posture: Zuree transcribes documents into structured data. It does not diagnose, interpret findings, read imaging, recommend treatment, or act as clinical decision support — and we decline feature requests that cross that line.

08 · Pricing

Flat monthly tiers with an included document quota.

A document is one file you send to /process. Deduplicated re-uploads and resumed retries are never billed twice. Overage is metered per document, so a spike costs money — not an upgrade conversation.

For pilots and first integrations

Starter

Get one workflow into production without a procurement cycle.

$490$417 /month
Billed monthly · cancel any timeBilled annually · $4,998 per year
Included documents
1,000 / month
Overage
$0.34 / document
  • All three V1 document types
  • Signed webhooks and full SDK access
  • FHIR R4 export and portable JSON
  • Email support, next business day
  • Two API keys, one environment
Start on Starter
Most common at production volume

Growth

For teams running claims intake or patient onboarding every day.

$2,450$2,083 /month
Billed monthly · cancel any timeBilled annually · $24,990 per year
Included documents
10,000 / month
Overage
$0.19 / document
  • Everything in Starter
  • Higher request and concurrency budgets
  • Configurable retention window per tenant
  • Separate sandbox and production tenants
  • Shared Slack channel, same-day response
  • Named onboarding engineer for 30 days
Choose Growth
High volume and regulated workloads

Scale

For insurers and platforms where document volume is the business.

$8,900$7,565 /month
Billed monthly · cancel any timeBilled annually · $90,780 per year
Included documents
60,000 / month
Overage
$0.11 / document
  • Everything in Growth
  • Volume-committed overage rates
  • Priority processing queue
  • Custom template onboarding for your top senders
  • Security review support and sub-processor disclosure
  • Contractual uptime and response targets
Talk to Scale
On every tier

All three V1 document types, LOINC coding, provenance, confidence, webhooks, the OpenAPI spec, the TypeScript SDK, FHIR R4 export and audited deletion. No feature is paywalled — only volume and support differ.

Not billed

Duplicate uploads (identical bytes), resumed retries of a checkpointed stage, documents returned as UNSUPPORTED, and every read of data you already have.

Sandbox

A free sandbox tenant with 100 documents comes with every technical evaluation, so you can benchmark accuracy on your own corpus before signing anything.

Volume calculator

What would your volume cost?

Drag to your expected monthly document count. We pick the cheapest tier for that volume, including overage.

4,200 documents / month
100120,000
Recommended · Starter
$1,578 /month
Platform fee$490
Included in tier1,000 docs
Overage · 3,200 docs$1,088
Effective cost per document$0.376
Book a technical demo

Estimates only, excluding tax. Annual billing applies a 15% discount on the platform fee; overage stays at the tier rate. Committed volumes above 120,000 documents per month are priced individually.

09 · Questions

The things security and eng ask first.

Something not covered? Bring it to the technical call — an engineer is on it, not just a rep.

Which document types does V1 support?+

Laboratory reports, prescriptions, and medical reports / clinical summaries. A document that Zuree recognizes but that falls outside that scope returns status UNSUPPORTED rather than a guessed extraction — and isn’t billed. Additional types are a roadmap conversation, not a silent expansion.

Does Zuree interpret results or make recommendations?+

No. Zuree transcribes and normalizes what the document says. It is not a diagnostic, medical-advice, radiology-interpretation, treatment-recommendation or clinical-decision-support system. The interpretation field on an observation reflects the flag printed on the source report against its own reference range — it is transcription, not judgement.

How do you handle a model returning bad output?+

AI output is treated as untrusted input. Every response is schema-validated before anything downstream reads it. Raw responses are kept immutably, separate from the normalized facts, so an extraction can always be re-derived and audited. JSON that had to be repaired or salvaged is flagged as such — it is never returned as clean. And no field silently defaults: a missing confidence stays missing rather than becoming a plausible number.

Is document content sent to a third-party AI provider?+

Yes — extraction requires it. Which provider and which exact model handled a given document is recorded on the extraction record and readable through GET /v1/documents/{id}/extraction, alongside prompt and pipeline versions. Providers sit behind an internal interface, so the mix can change; the attribution on each record tells you exactly what processed what. Provider handling is governed by their contract, which we’ll share in diligence.

What are the rate limits?+

Numeric limits are set per deployment and plan, not fixed in the API contract — your tenant’s are stated on your account. The mechanism is stable regardless: a 429 with Retry-After, which the SDK honors automatically with backoff and jitter. Bulk processing queues against a concurrency budget instead of being rejected, so submitting a thousand documents at once is fine.

Can we get our data out, and can we get it deleted?+

Both. A complete portable JSON export per patient includes per-document provider accounting, and the clinical data is also available as FHIR R4. Deletion is explicit and tenant-initiated — DELETE /v1/documents/{id} removes a document and its derived data across the database, object storage, queue and temporary files, leaving an audit record of who and when, never of what.

What counts as a billable document?+

One file that completes a processing run. Re-uploading identical bytes returns the existing document with "duplicate": true and isn’t billed again. A retry that resumes a checkpointed stage doesn’t re-bill the AI call for a stage that already finished. Reads of data you already hold are unmetered.

Docs

Full API reference

Every endpoint and field, with curl and SDK examples side by side.

Read the docs →
SDK

@zuree/sdk

Typed TypeScript client with auto-pagination, retry and webhook verification.

npm i @zuree/sdk
Spec

OpenAPI, live

Generate a client in your language from the running deployment's own spec.

/v1/openapi.json
Interop

FHIR R4 export

The same clinical model, rendered as FHIR resources for your existing stack.

See the mapping →
Book a technical demo

Bring us ten of your ugliest documents.

Forty-five minutes with an engineer, not a pitch. We run your real files through the pipeline, show you the extraction records and the provenance, and tell you plainly where it struggles.

Book a technical demo Get sandbox access

Sandbox tenant with 100 free documents. No card, no procurement.