|API reference

Everything is one POST away.

All requests and responses are JSON unless you ask for raw ER7. Errors follow RFC 7807 problem+json. No API key is required during the preview — keys and rate limits arrive with early access.

base url https://gzp3bhmytd.us-east-1.awsapprunner.com

POST /v1/generate

Generates a FHIR R4 transaction Bundle — Patient, Practitioner, Encounter, Conditions, and DiagnosticReports with their Observations. Response content type is application/fhir+json. Clean-profile output validates against base R4.

Query parameterTypeDescription
presetstringNamed preset scenario. See presets. Wins over every other input.
scenariostringPlain-English scenario, translated to a spec by Scribe. URL-encode it, or send it in the body instead.
seedintegerDeterministic seed. Same seed + same spec → byte-identical output. Defaults to 42.
profilestringclean · epic-like · cerner-like · dirty. Defaults to clean.
Body (optional)TypeDescription
{"scenario": "..."}objectSame as ?scenario=, without the URL-encoding.
{...spec}objectA full scenario spec. Used when no preset or scenario is given.
curl -X POST 'https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/generate?preset=chf-ckd-admit&seed=42' curl -X POST https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/generate \ -H 'Content-Type: application/json' \ -d '{"scenario": "62F with CHF and stage-3 CKD, admitted via ED, 5 day stay"}'
POST /v1/hl7v2/generate

Generates a coherent HL7 v2.5.1 message sequence for the same clinical story: optional ED registration (ADT^A04), admit (ADT^A01), one ORU^R01 per lab panel, and a discharge (ADT^A03) when the stay has a length. Every message survives an NHapi parse round-trip.

Query parameterTypeDescription
preset / scenario / seed / profileIdentical to /v1/generate.
formatstringraw returns concatenated ER7 text (text/plain). Omit it for a JSON envelope with one entry per message: type, trigger event, event time, content.
curl -X POST 'https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/hl7v2/generate?preset=chf-ckd-admit&seed=42&profile=dirty&format=raw'

The same seed produces the same patient here and in /v1/generate — same name, MRN, and lab values in both standards.

GET /v1/scenarios/presets

Lists the built-in preset scenarios as a map of name → full scenario spec. Current presets: chf-ckd-admit, diabetic-ed-visit, sepsis-admit.

curl https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/scenarios/presets
POST /v1/sandbox/tenants

Creates a private HAPI FHIR partition and returns a sandbox key scoped to it. The key is a tenant id plus an HMAC over it — nothing is stored server-side, so it's shown once and can't be retrieved again. Send it as x-sandbox-key on every seed and read call below; one tenant can never see another's data.

curl -X POST https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/sandbox/tenants
POST /v1/sandbox/seed

Generates a bundle and pushes it into your sandbox partition as a transaction, returning the IDs of every created resource. Takes the same inputs as /v1/generate.

HeaderDescription
x-sandbox-keyFrom /v1/sandbox/tenants. Omit it and the seed lands in the shared preview partition instead of a private one.
curl -X POST 'https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/sandbox/seed?preset=chf-ckd-admit' \ -H 'x-sandbox-key: shk_...'
GET /v1/sandbox/fhir/{path}

Read-only proxy into your partition — pass any FHIR REST read (Patient, Patient?identifier=..., Observation/123, metadata) with the same x-sandbox-key header. The raw HAPI sandbox URL isn't public; this is the supported way in.

curl https://gzp3bhmytd.us-east-1.awsapprunner.com/v1/sandbox/fhir/Patient \ -H 'x-sandbox-key: shk_...'

Choosing the scenario input

Both generate endpoints resolve their input in a fixed order — preset, then natural-language scenario, then a spec body. Presets and specs are fully deterministic. Natural-language scenarios pass once through Scribe, our clinical-language engine, which writes the structured spec (cached for 24 hours) — after that, generation is deterministic too. Scribe only designs the spec; it never writes a segment or a resource.

Scenario spec schema

The structured contract behind every generation. All fields are optional; defaults are shown.

FieldTypeDescription
seedinteger = 42Drives every random draw. Overridable per request with ?seed=.
ageinteger = 50Patient age in years, 0–120. Date of birth is derived so the age is exact at the reference date.
sexstring?female · male · other · unknown. Omit to let the seed pick.
conditions[]arrayDiagnoses: {"icd10Code": "I50.9", "text": "..."}. Display text is filled from the built-in ICD-10 table when omitted. Conditions skew lab values — a stage-3 CKD patient's creatinine comes back 1.6–2.6 flagged H.
encounter.classstring = inpatientinpatient · emergency · outpatient.
encounter.admitViaEdbool = falseAdds an ED registration (ADT^A04) before the inpatient admit.
encounter.lengthOfStayDaysinteger = 3Days from admit to discharge, 0–60. 0 means no discharge message.
encounter.labPanels[]array = [cbc, bmp]Panels resulted in order, up to 20. Available: cbc, bmp.

Noise profiles

Rule-based, deterministic post-processors that make clean output look like production. FHIR quirks always stay strictly parseable.

ProfileWhat it injects
cleanNothing. Validates against base R4; the baseline for golden-file diffs.
epic-likeUppercased patient names; a redundant second MRN under a local EPI-style system.
cerner-likeMRNs zero-padded to 10 digits everywhere they appear; hospitalization details dropped.
dirtyUppercased names, dropped telecoms, every third result loses its reference range and abnormal flag, timestamps truncated to date-only precision.

Errors

Every error is an RFC 7807 problem+json body with title, detail, and status.

StatusWhen
400Unknown profile, invalid spec body, age or length-of-stay out of range, more than 20 lab panels, or no scenario input at all.
404Unknown preset name.
502Scenario translation or sandbox upstream failed — safe to retry.
503Natural-language translation isn't enabled on the deployment. Use a preset or a spec body instead.
{ "title": "Unknown profile", "detail": "Profile must be one of: clean, epic-like, cerner-like, dirty. Got 'messy'.", "status": 400 }