Skip to content

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.

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)
  1. Launch leg — GET /smart/launch. The EHR redirects the clinician’s browser here with an iss (the EHR’s FHIR base URL) and an opaque launch token. BirthTracks discovers the EHR’s authorization server from the iss, mints a PKCE verifier/challenge (S256) and a state, and redirects the clinician to the EHR’s authorization endpoint with the launch context bound to the aud.
  2. Callback leg — GET /smart/callback. The EHR returns the clinician here with a code and the state. BirthTracks validates the state, 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.
  3. Map. The USCDI Patient, Observation, Condition and Encounter resources 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.
  4. 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.

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).

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.

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 a client_id is configured, /smart/launch returns 503. 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/callback on the BirthTracks host.
    • Scopes requested: launch openid fhirUser patient/Patient.read patient/Observation.read patient/Condition.read patient/Encounter.read.
  • Issuer allowlist (security). The incoming iss is checked against the allowlist before any network call, so an iss pointed at an internal address or a phishing host is rejected up front with 403. 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.