Skip to content

Universal Ingestion Flow

This guide explains how to send patient-intake data (demographics, vitals, presenting symptom, conditions and more) to HAMI through a single FHIR-native endpoint. It also shows how that one call leads to patient intake, the AI summary and, optionally, HAMI Scribe for the clinician.

  • Purpose: Let referral partners and EHRs send patient-intake data to HAMI in one FHIR request.
  • High-level flow: Partner submits a FHIR Bundle (type=transaction) → HAMI validates the FHIR structure → HAMI matches or creates the patient, creates the appointment and stores the bundle → HAMI responds with a transactionId and any links enabled for your group. All of this happens synchronously, within the request.
  • Standards: FHIR R4 (HL7). UCUM for units, LOINC/SNOMED CT/ICD-10 for terminology.
  • Audience: Partner engineers, EHR integrators, interface analysts, health-data vendors.

{HAMI_API_BASE_URL}/api/g/{group-slug}/ingestion/fhir/v4

HAMI provides the base URL for each environment, your group slug and your API key during onboarding.

  • An API key is issued per group and sent in the X-API-KEY header.
  • Required: a Bundle with type: "transaction" that contains a Patient.
  • Strongly recommended:
    • Patient.telecom (phone) and/or an MRN identifier, so the patient is matched rather than duplicated
    • Patient.gender and Patient.birthDate
    • Patient.communication (preferred language)
    • An Appointment, for the visit date and time
    • An Observation with category symptom, for the presenting symptom

Any structurally valid FHIR R4 resource is accepted and stored with the transaction. HAMI actively uses Patient, Appointment and symptom Observation resources. See Supported Resource Types.

Rule: References inside the bundle should resolve to a fullUrl in the same bundle.

POST /api/g/{group-slug}/ingestion/fhir/v4

Headers:

  • Content-Type: application/json
  • X-API-KEY: <group-api-key>
  • x-correlation-id: <your-id> (optional; echoed back so you can trace the request)

Body: FHIR Bundle (type: "transaction")

Success (201 Created)

{
"transactionId": "0192f3a1-7c4e-7b2a-9d1f-3e5a6b7c8d90",
"url": "https://hamiapp.bostonhealth.ai/g/group-slug/transaction/0192f3a1-7c4e-7b2a-9d1f-3e5a6b7c8d90"
}

Depending on your group’s configuration, the response can also include qrCodeImage, embedUrl, scribeLaunchUrl and appointmentUrl. See the response reference.

One ingestion call can drive the whole visit, from patient intake to the signed clinical note:

Your system HAMI Patient / Clinician
─────────── ──── ───────────────────
1. POST FHIR Bundle ───────────────► Store bundle, match or create
patient, create appointment
◄──────────── 201 { transactionId, url, qrCodeImage?,
embedUrl?, appointmentUrl?, scribeLaunchUrl? }
2. Hand the intake to the patient:
• show qrCodeImage (kiosk / printout) ───────────────────────────► Patient scans, completes intake
• load embedUrl in your iframe ──────────────────────────────────► Patient completes intake in your portal
• send appointmentUrl / url (SMS, email) ────────────────────────► Patient opens link, completes intake
3. ◄──────────── Intake Summary Webhook { appointmentId, transactionId,
emergency_patient, intakeSummary, ... }
4. Open scribeLaunchUrl in your EHR ────────────────────────────────► Clinician signs in, records visit,
signs off SOAP note
5. ◄──────────── Scribe Webhook { soapNote, transcript, icdCodes,
cptCodes, afterVisitSummary, sourcePatientId, ... }
StepFeatureReference
1Universal Ingestion APIUniversal Ingestion API
2QR code, embedded intake, appointment linkOptional response features, Iframe Embedding
3Intake summary pushIntake Summary Webhook
4Embedded ScribeScribe Embedding
5Scribe note pushScribe Webhook

Each step after step 1 is optional and enabled per group. Most integrations start with steps 1–3 and add Scribe (steps 4–5) later.

To get…Include…
A matched (not duplicated) patientA phone number in Patient.telecom (matched together with first and last name), and/or an MRN in Patient.identifier with type code MR (used when there is no phone number)
Correct demographicsPatient.gender and Patient.birthDate. HAMI stores placeholder values if they are missing.
Intake in the patient’s languagePatient.communication with the preferred language
Your IDs back in the webhooksStable fullUrl values on the Patient and Appointment entries, and an MR identifier on the Patient
The visit time on the physician dashboardAn Appointment resource. Without one, HAMI creates an appointment at the time of ingestion.
Presenting symptom passed to the AI intakeAn Observation with category code symptom and the symptom in valueCodeableConcept.text

HAMI validates every resource in the bundle against the FHIR R4 structure definitions. Unknown elements and wrongly typed values are rejected with 400 Bad Request. Terminology bindings and profiles are not checked on the server, so validate your bundles locally before sending (for example with the HL7 FHIR Validator).

  • Vitals: LOINC (e.g., BP 85354-9, HR 8867-4, RR 9279-1, Temp 8310-5, SpO₂ 59408-5 for pulse-ox).
  • Diagnoses/Complaints: SNOMED CT preferred, ICD-10-CM accepted.
  • Units: UCUM (e.g., mm[Hg], kg, Cel, /min).
  • Bundle.type should be "transaction".
  • References: point to a fullUrl within the bundle. Prefer urn:uuid: values.
  • Identifiers: put MRNs and external IDs in identifier[] with system URIs. Mark the MRN with type code MR.
  • Narratives: text.div must be valid XHTML. Never put secrets or keys in narratives.

The API is not idempotent. Every successful request creates a new transaction and a new appointment. The patient profile is reused when it matches (see How the patient is matched).

  • Send one bundle per visit, and don’t resubmit after a 201.
  • Retry only 5xx responses and network failures, with exponential backoff. If you’re unsure whether a timed-out request succeeded, contact support with your x-correlation-id before resending.

All errors return { statusCode, message, correlationId }:

StatusWhen
400Invalid JSON, or the bundle fails FHIR R4 structural validation
401X-API-KEY missing or not valid for this group
404Unknown group slug
500Unexpected server error. Contact support with the correlationId.

See Error Responses for examples.

  • Maximum request size: 50 MB.
  • Contact support before sending bulk or backfill volumes.
  • Use stable identifiers: always send identifier.system URIs (MRN, external referral ID).
  • Normalize vitals: UCUM units, one LOINC code per Observation.
  • Choose plausible values: e.g., adult body weight ≥ 30 kg unless a pediatric context is explicit.
  • Reference hygiene: every reference should resolve to a fullUrl inside the transaction.
  • Time semantics: use UTC ISO 8601 (e.g., 2025-09-25T09:41:00Z).
  • Testing: validate bundles locally before submitting, and start in the HAMI test environment provided at onboarding.

Q: Can we send partial data?

A: Yes. Only a Patient is required. Send what you have and HAMI’s AI intake collects the rest from the patient.

Q: How do we update a prior record?

A: Records can’t be updated through this API. A new submission creates a new transaction and appointment for the same (matched) patient. Contact support if you need a correction.

Q: Can we send PDFs/images?

A: A DocumentReference with base64 content is accepted and stored with the transaction (up to the 50 MB request limit). It is not currently passed to the AI intake.