Ingest a FHIR Bundle
POST a FHIR R4 or R5 Bundle, poll the receipt it returns, and read what the submission could not use.
Ingest a FHIR Bundle
Send a FHIR Bundle (or any single FHIR resource) to register it against a patient. The patientId in the URL is your registry key — the stable identifier used in all subsequent calls for this patient.
The FHIR release is part of the path, because a Bundle does not state which release it is written against. Post R4 payloads to /ingestions/fhir/r4 and R5 payloads to /ingestions/fhir/r5.
Make the request
Create the patient before the first ingest:
curl -X PUT "https://<workspace-id>.w.clinia.cloud/v1/patients/{patientId}" \
-H "Authorization: Bearer <access-token>"This call is idempotent, so it's safe to run before or after your first ingest.
curl -X POST "https://<workspace-id>.w.clinia.cloud/v1/patients/{patientId}/ingestions/fhir/r4" \
-H "Authorization: Bearer <access-token>" \
-H "Content-Type: application/json" \
-d @fhir-bundle.jsonA successful call answers 202 with a receipt:
{
"ingestionId": "c1m2k3n4p5q6r7s8t9u0v1w2",
"source": "fhir/r4",
"mimeType": "application/json",
"receivedAt": "2026-09-10T14:22:31.004Z",
"status": "pending",
"staged": { "facts": 12, "events": 8, "narratives": 1 },
"intake": [
{
"unit": "resource",
"received": 42,
"entries": [
{ "kind": "Condition", "count": 4, "outcome": "structured" },
{ "kind": "Observation", "count": 30, "outcome": "structured" },
{ "kind": "DocumentReference", "count": 1, "outcome": "text_only" },
{ "kind": "ImagingStudy", "count": 7, "outcome": "ignored", "reason": "unsupported" }
]
}
],
"startedAt": null,
"completedAt": null,
"failure": null
}202 means accepted, not finished. Extraction continues after the response, so nothing is queryable when the call returns. ingestionId is the only handle you need to keep — poll it to follow the work. See Ingestion for what happens between acceptance and a settled submission.
startedAt is null until the work is picked up — the gap from receivedAt is queue wait, not time spent processing.
staged counts the rows this submission actually contributed. Re-sending content that is already stored stages nothing and reports zeros, which is how a duplicate delivery is distinguished from a new one.
Request details
The body must be a valid FHIR JSON document — either a Bundle or a single resource such as Patient, Condition or MedicationRequest — and Content-Type must be application/json.
Supported resource types include: Patient, Condition, MedicationStatement, MedicationRequest, Observation, AllergyIntolerance, Coverage, Immunization, Procedure, Encounter, FamilyMemberHistory, Device, DeviceUseStatement, DeviceUsage, and DiagnosticReport.
Each call is one submission and one receipt. Multiple calls for the same patientId accumulate sources, and entity resolution re-runs over everything accumulated.
Clinical prose. A DocumentReference contributes no entities. Its text attachment becomes a narrative instead — kept verbatim, readable under /sources/, and adjudicated against the facts it speaks to. The attachment must be inline (data) or a Binary in the same bundle, and one of text/plain, text/html or application/xhtml+xml. A remote url, or any other content type, appears in intake as text_only turning to ignored — so a bundle can carry documents and contribute none of their prose.
Error responses
Validation is synchronous: a malformed payload is rejected before anything is staged.
| Status | Cause |
|---|---|
400 | Request body is not valid JSON or is missing a resourceType field |
404 | No such patient |
422 | Bundle contains no extractable FHIR resources |
Follow the submission
Poll the receipt until it settles:
curl "https://<workspace-id>.w.clinia.cloud/v1/patients/{patientId}/ingestions/{ingestionId}" \
-H "Authorization: Bearer <access-token>"status says where the submission stands across all its work. The possible values are:
pending- Accepted, not startedprocessing- In flightsucceeded- Everything landed and is searchablepartial- Searchable, but some of what you sent is missingfailed- The work stopped before finishing; readfailurefor the reason
To ask whether a patient's data has settled rather than watching one submission, filter the listing:
curl "https://<workspace-id>.w.clinia.cloud/v1/patients/{patientId}/ingestions?status=pending,processing" \
-H "Authorization: Bearer <access-token>"meta.total is the number of submissions still outstanding. Zero means this patient has settled.
Read what was not used
intake accounts for every resource you sent, grouped by kind and outcome, so a submission never silently discards part of itself. It is fixed when the request is accepted and never recomputed.
Each entry's outcome says what was done with resources of that kind. The possible values are:
structured- Clinical detail was read from ittext_only- Kept, but as prose — no structured detail was readignored- Not used at all;reasonsays why
An ignored entry carries a reason, and the reasons are differently actionable. The possible values are:
unsupported- The type is not modelled yet — nothing to fix, it may be used laterunusable- Recognised, but missing what it needs (no code, no text)empty- Recognised and well-formed, but carries no extractable content
For the resolved picture across every source, use the reconciliation summary.
Submitting several documents
Each call carries one Bundle, and a Bundle is already a collection — put several resources in one and post it once. For several independent Bundles, make several calls. How that work is divided internally is decided for you, so nothing about the grouping needs to be expressed in the request.