Skip to main content
FHIR is a representation, not a second API. Every resource below is the SAME record, on the SAME endpoint, with the SAME scope, entitlement, clinic scoping and audit trail as our plain JSON — only the shape on the wire changes, selected by a standard header.

Reading a resource as FHIR

Send Accept: application/fhir+json on any of these existing GET endpoints: A list becomes a Bundle of type: searchset, with link entries for the current page and, when there’s another page, the next one — the same page you’d get back from starting_after on the plain JSON response. A single read returns the bare resource.

Writing a resource as FHIR

Send Content-Type: application/fhir+json on:
  • POST a Patient to create one, or PATCH it to update one. Updates are PATCH, never PUT.
  • Patient writes do not carry allergies, current_medications or chronic_conditions: they are refused. See Allergies and Conditions.
  • POST an Appointment to create one, or PATCH it to update one — the appointment must reference a HealthcareService (your clinic’s service) in basedOn; there is no unscheduled-service appointment.
  • POST a DocumentReference to create a note — always lands as a draft (docStatus: preliminary). Nothing in FHIR can sign a note; that stays a clinician action in the product itself. docStatus: final (or anything else) on a create is refused.
  • POST a Condition to send one for review, or PATCH it to ask for a change. The response is 202 Accepted: a clinician decides whether it reaches the chart. See Conditions.
  • ServiceRequest is read-only as FHIR. Send and change referrals with the JSON routes in Referrals; a FHIR body is refused with an OperationOutcome.
  • Encounter is read-only as FHIR. Open and change visits with the JSON routes in Encounters; a FHIR body is refused with an OperationOutcome. A visit whose type is not known is shown with the FHIR code for unknown, never a guessed type.
  • MedicationStatement and MedicationRequest are read-only as FHIR. Send and change reported medicines with the JSON routes in Medications; prescriptions cannot be written at all. A FHIR body is refused with an OperationOutcome.
  • AllergyIntolerance is read-only as FHIR. Send and change allergies with the JSON routes in Allergies; a FHIR body is refused with an OperationOutcome.
The body is converted to the exact same shape our plain JSON body is, then validated and written through the identical path — a FHIR write and a JSON write can never disagree about what a record looks like afterward. A write is answered in our plain JSON shape, not as FHIR, even when you sent a FHIR body. To read the record back as FHIR, GET it with Accept: application/fhir+json. An element that would change a record’s meaning without anywhere for it to go is refused, not silently dropped. On Patient: gender: "unknown", deceasedBoolean/deceasedDateTime, multipleBirthBoolean/multipleBirthInteger, and Patient.link (merging two records is a staff-reviewed decision, never something an API write can assert). A refusal on a FHIR request comes back as an OperationOutcome, not our usual error shape — see Errors for how the same underlying error code appears in both.

Automatic acceptance

An allergy, condition or reported medicine that a clinic accepted automatically is rendered with verificationStatus unconfirmed, plus an accepted_by extension (a string, automatic), until a clinician marks it reviewed. After that it reads confirmed. It is never presented as clinician-confirmed before then. See Automatic acceptance.

What isn’t here

  • No _include/_revinclude on any search.
  • No FHIR-standard search parameters. Each resource is searched with the query parameters its endpoint really accepts, under our own names (for example patient_id, not patient). They are listed below, and in the CapabilityStatement. A search is paged with limit and starting_after; a Bundle carries a next link and no total, because the total is not computed.
  • No general /fhir passthrough, and no arbitrary FHIR resource type.
  • Coverage and payer Organization are read-only in FHIR: a FHIR body on POST or PATCH is refused with an OperationOutcome, so add or change a coverage in the plain JSON shape. See Insurance.
  • Practitioner is read-only. The provider directory cannot be written by any request, in any shape. See Providers. PractitionerRole is not available yet: a clinician’s role and specialties are carried on the Practitioner.
  • Outside care providers have no FHIR shape. They are JSON only, and a FHIR body or Accept: application/fhir+json on those routes is refused. See Outside care providers.
  • No Location, Slot, Schedule, or HealthcareService create/update through FHIR — read/write for those stays on their own plain endpoints as they ship.
  • No exact stock quantity in FHIR — a medicine’s availability is carried as a coarse band (out / low / in_stock), the same one the plain JSON endpoint returns, never an exact count.
  • No sign, lock, or finalize on a note, from any door.

Search parameters

GET /v1/metadata returns a FHIR CapabilityStatement listing exactly what’s supported — treat it as the source of truth over this page if the two ever disagree.

Importing a list of patients

You can bring a list of patients in from another system at once, instead of creating them one at a time. Accepted formats: a FHIR Bundle of Patient resources, an NDJSON file (one Patient object per line), or a plain JSON array in our own patient shape. A file may hold at most 100 rows and 10 MB. What happens:
  1. Every row is checked first — required fields, valid values, dates that make sense. Nothing is written yet.
  2. Any row with an error stops the whole file. You get back exactly which row, which field, and why — never the value that failed, and never a partial import. Fix the file and upload again, or choose to import only the rows that passed.
  3. A clean file imports automatically. Each patient is created the same way a single create would be. A possible duplicate (matching an existing patient closely) is still created — never silently merged, never silently refused — and flagged for your staff to review in the product.
  4. Re-uploading the exact same file is a no-op — you’ll get told it was already imported, not a second copy of every patient.
  5. An import never sends a message to a patient and never starts an automation on their behalf.
Allergies, current medications and chronic conditions are not accepted in a patient import, or on a patient create or update. A row that carries allergies, current_medications or chronic_conditions is refused. Send allergies with Allergies and conditions with Conditions; both are reviewed by a clinician before they reach the chart. Current medications cannot be set through the API. You’ll get back four counts when it finishes: how many were created, how many were flagged as a possible duplicate, how many were skipped because they were already imported, and how many failed.