Start building

Developer guide

Referrals: enrolling a patient you created

Refer your patient to the medical group that covers your brand; the group accepts, the patient accepts with consent and the program terms, and intake opens.

Open the Developer Center

Never send patient information to a sandbox key.

On this deployment: Headless clinical API (patient data): Not available · Headless Connect API: Not available in this environment
  • Headless clinical API (patient data): Not available. What runs now: Nothing for a real patient: the headless patient API is written and has run only against a local synthetic stack; no brand's patient data access is approved in any environment, and the Developer Center's clinical-loop simulator is a script with synthetic ids.
  • Headless Connect API: Not available in this environment. What runs now: Sandbox-key calls to /api/v1 on the nonproduction deployment with synthetic data: claims scan, formulary, rulebook, the sandbox order preview, delivery reads and replay, and the MCP endpoint, on a deployment whose database has the 20261101090000-range migrations applied (a hard deploy-order dependency the merge gate enforces; ahead of them the rulebook, claims scan, MCP and replay answer 503).

Why a referral

On live data an intake draft or submission is accepted only for a program and State the patient holds an accepted enrollment for; without one both answer 422 enrollment_required. A patient you create with POST /patients holds none. A referral is how they get one without an inviting clinician: you refer, the medical group covering your brand accepts, and the patient accepts in your app.

Status: written, not open. The headless patient API exists on the developer sandbox build and has run only against synthetic data; no brand's patient data access is approved in any environment yet, and there are no live PHI keys.

The four calls

  1. POST /patients/{patientId}/referrals {programHandle, state, externalReference?} (intake.write). Every eligibility rule applies except the program's self-serve switch. The answer is the referral, usually pending_group_review.
  2. Wait for clinical.referral.accepted (or .declined, with a coarse declineReason; a referral with no next step for 30 days sends clinical.referral.expired), or read GET /patients/{patientId}/referrals/{referralId}.
  3. In your app, show and record every consent the program requires (POST /patients/{patientId}/consent-presentations, then /consents with render receipts) and show the program's terms, whose digest is disclosure.digest in GET /catalog/{brand}/programs/{handle}.
  4. From the patient's signed-in session: POST /patients/{patientId}/referrals/{referralId}/accept {termsDigest}. The referral is enrolled and names its enrollmentId; intake drafts and submissions for the program and State are accepted from then on.
SDK (Node server only)
const p = ambition.patients(patientId, { session, auth: "passkey" });
const referral = await p.referrals.create({ programHandle, state: "AZ" });
// ... clinical.referral.accepted arrives; consents recorded; terms shown ...
const enrolled = await p.referrals.accept(referral.id, program.disclosure.digest);
await p.intake.submit({ /* the program's questionnaire answers */ });

Who accepts: the medical group's policy

The group's acceptance policy, set by its medical director
PolicyWhat happens to a referralNeeds
group_review (default)Waits for a member of the group (administrator or medical director) to accept or decline itNothing
self_enrollmentAccepted by the group's policy at once (acceptance: group_policy)The group's written ruling, and the program's self-serve switch on; otherwise it still waits for review

On live data the group's medical director must also have authorized enrollment for your brand, program and State (enrollment_authorization_required otherwise). A referral waiting for the group, or accepted and waiting for the patient, expires after 30 days. You can withdraw an open referral; once the patient accepted, cancel their case instead. A decline sticks: the same patient, program and State cannot be referred again for 30 days, and a later referral always goes to the group's review. termsDigest is your attestation that the patient was shown the program's terms; Ambition checks it is the current digest.

In the sandbox

The sandbox medical group decides for you: POST /sandbox/patients/{patientId}/referrals/{referralId}/simulate {decision: accept | decline, reason?} (SDK: p.sandbox.decideReferral). It goes through the same decision a group member's does, emits the same clinical.referral.* event with livemode false, and marks the referral sandboxDecision: true. Sandbox keys and synthetic brands only.