SMART on FHIR (EHR launch)
There are two ways a birth reaches BirthTracks from another system, and this is the second one:
- Push — an EHR or integrator POSTs a FHIR R4 Bundle to the ingestion endpoint. This is the server-to-server lane in Getting started and Partner onboarding.
- Pull (this page) — a clinician launches BirthTracks from inside their EHR; we read the launched patient’s data back over SMART on FHIR and use it to pre-fill a course of care the clinician then reviews and submits.
The pull lane is an interactive, one-record path — a clinician mid-visit — not a bulk feed. It carries no API key: the clinician’s own EHR session is the authorization.
The launch flow
Section titled “The launch flow”BirthTracks implements the standard SMART App Launch (v2) EHR-launch sequence — OAuth2 authorization code with PKCE.
sequenceDiagram
participant C as Clinician (in EHR)
participant BT as BirthTracks
participant AS as EHR auth server
C->>BT: GET /smart/launch?iss=…&launch=…
BT->>AS: discover, then redirect (PKCE + state + aud)
C->>AS: authorize (EHR session)
AS->>BT: GET /smart/callback?code=…&state=…
BT->>AS: exchange code + PKCE verifier → access token
BT->>AS: read the patient's USCDI resources
BT->>C: /registry/capture/prefill (Pre-fill from the EHR)
- Launch leg —
GET /smart/launch. The EHR redirects the clinician’s browser here with aniss(the EHR’s FHIR base URL) and an opaquelaunchtoken. BirthTracks discovers the EHR’s authorization server from theiss, mints a PKCE verifier/challenge (S256) and astate, and redirects the clinician to the EHR’s authorization endpoint with the launch context bound to theaud. - Callback leg —
GET /smart/callback. The EHR returns the clinician here with acodeand thestate. BirthTracks validates thestate, exchanges the code (with the PKCE verifier) for an access token carrying the patient context, and reads that patient’s USCDI resources back from the EHR. - Map. The USCDI
Patient,Observation,ConditionandEncounterresources are mapped onto the canonical registry spine by a US Core mapper. It is a different mapper from the push lane’s Bundle mapper — the two share the spine they write into, not the mapping code. - Pre-fill —
GET /registry/capture/prefill. The mapped values land on a Pre-fill from the EHR review screen. The clinician reviews them, completes the rest, and saves; the save records a registry course of care and returns to Records. It does not open the Record a birth form or add a Births-log birth.
The launch, callback and USCDI-read legs are public — there is no app account in that handshake; the clinician’s EHR session authorizes them, exactly like the app’s other identity-provider entry points.
Where the record lands
Section titled “Where the record lands”Persisting a course of care lands it in a practice, so the write leg — the Pre-fill from the EHR screen’s save — requires a signed-in practice user with a record-managing role (practice admin, provider, or a write-only Scribe seat). A public handshake never writes into a tenant. The mapped pre-fill rides the session across the login redirect, so a clinician who wasn’t signed in yet still lands on the pre-fill screen after authenticating.
The save records a registry course of care through the same write path as the
registry’s manual and CSV lanes — it appears under Records, not in the Births
log — so it is identical to a hand-keyed registry record; only its
provenance differs. Every value the EHR supplied is stamped with the
submission source ehr_pull (EHR pull), tied to the mother or child it
describes, so an auditor can tell EHR-sourced fields from ones the clinician
entered. The other sources are manual, csv, and fhir_push (the Bundle
push lane).
Rate limiting
Section titled “Rate limiting”The callback is throttled to 10 requests per minute per source IP (the
smart-callback limiter). Because there is no app user at the callback, the
client IP is the only key available. The pre-fill submit runs under the app’s
normal authenticated session, not this limiter.
Availability and configuration
Section titled “Availability and configuration”This lane is inert until an operator provisions it, so there is nothing to call until your EHR is onboarded:
- Per-EHR-vendor registration. Each EHR vendor is registered individually —
a
client_id, the redirect URI, and the vendor’s FHIR base added to an issuer allowlist. Until aclient_idis configured,/smart/launchreturns503. The facts a vendor’s app registration needs:- Client type: public client — no client secret; the code exchange is
protected by PKCE (
S256). - Redirect (callback) URI:
/smart/callbackon the BirthTracks host. - Scopes requested:
launch openid fhirUser patient/Patient.read patient/Observation.read patient/Condition.read patient/Encounter.read.
- Client type: public client — no client secret; the code exchange is
protected by PKCE (
- Issuer allowlist (security). The incoming
issis checked against the allowlist before any network call, so anisspointed at an internal address or a phishing host is rejected up front with403. An empty allowlist trusts nothing.
There is no self-service path to enable the EHR-launch lane. Contact your BirthTracks representative to start vendor registration.
Related
Section titled “Related”- Record a birth — the manual capture form (the pre-fill does not use it).
- Getting started — the push (FHIR Bundle) lane.
- Data dictionary — the canonical spine the USCDI is mapped onto.