Developer-Consented Patients (Enterprise Only)
By default, every request goes through the Appendix consent page: your user reviews what's being submitted, consents to care from Appendix, and verifies their identity. Organizations with an enterprise agreement can skip that step for patients who have already consented directly with them — create the patient via API, get back a patient_id, and submit requests for it with no consent modal.
What the enterprise agreement covers
Production use of this flow is available only under an enterprise agreement with Appendix (contact hello@appendix.com). Under it, your organization — not Appendix — is responsible for:
- Obtaining and documenting consent directly with each patient: consent to receive care from Appendix physicians, to share their information with Appendix, and for Appendix to share the details of that care back to your organization.
- Verifying each patient's identity. Appendix does not run its own identity verification for developer-consented patients.
Each POST /prescribing/patients call attests to this (consent_attested: true), and the optional consent_reference lets you link our record to your own consent documentation. Keep it opaque — never put personal information in it.
Test data only, until you're under contract
Never submit real personal information in sandbox — or in any environment until an enterprise agreement is signed and your production access is approved. Appendix enables this flow on your account — it isn't a setting you switch on yourself. Once enabled, your test keys work immediately, so you can build the whole integration against simulated decisions with made-up patients while the agreement is being signed. Production keys stay rejected until your production access is approved. Your dashboard's Consent tab shows which consent model your account is on; to change it, email hello@appendix.com.
1. Create the patient
All demographic fields are required, plus patient_ref — your own identifier for this person, which is what we deduplicate on. The response returns the patient_id you'll submit with.
patient_ref is required, and it is the deduplication key
Pass whatever primary key you already store for this patient — a UUID, an MRN, a row ID. It is opaque to us: we never parse it, and it never needs to mean anything to anyone but you. It must be stable per person, since that is what makes repeat calls safe.
- Omitting it fails. A create with no ref returns
400patient_ref is required. - Reusing one for a different person fails. A ref your app has already used, but with a different name or date of birth, returns
409patient_mismatchrather than silently creating a second record or overwriting the first. One ref, one person. - Reusing one for the same person succeeds. Same ref, name, and date of birth returns the existing record with
200. Retries are safe, and you don't need to track whether you already created the patient.
# Your own primary key for this person. Anything stable and unique
# within your app — we never interpret it.
"patient_ref": "550e8400-e29b-41d4-a716-446655440000"
"patient_ref": "MRN-88213"
"patient_ref": "88213"
# Rejected: empty, >256 chars, or containing line breaks / control characters.Refs are compared exactly (trimmed, case-sensitive) because they are identifiers, not names. Names are compared case-insensitively, so incidental capitalisation differences don't block a legitimate retry.
Patient records are scoped to your app and to one environment. The same ref in sandbox and in production is two separate patients, so testing never affects your later production use of it.
curl -X POST https://api.appendix.com/api/v1/prescribing/patients \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ada",
"last_name": "Lovelace",
"date_of_birth": "1992-03-14",
"sex": "female",
"state": "PA",
"zip": "19103",
"phone": "+14155550123",
"patient_ref": "550e8400-e29b-41d4-a716-446655440000",
"email": "patient@example.com",
"consent_attested": true,
"consent_reference": "consent_rec_9917"
}'
{
"patient_id": "6f2d...",
"first_name": "Ada",
"last_name": "Lovelace",
"date_of_birth": "1992-03-14",
"sex": "female",
"state": "PA",
"zip": "19103",
"phone": "+14155550123",
"patient_ref": "550e8400-e29b-41d4-a716-446655440000",
"email": "patient@example.com",
"sandbox": false,
"external_consent": { "attested_at": "2026-07-17T15:04:05Z", "reference": "consent_rec_9917" },
"created_at": "2026-07-17T15:04:05Z"
}Read a patient back any time with GET /api/v1/prescribing/patients/{id}:
curl "https://api.appendix.com/api/v1/prescribing/patients/6f2d..." \
-H "Authorization: Bearer ak_live_..."About the email address
email is optional and purely record-keeping. Send it if you have it: the physician sees it as context, and it helps when the two of us reconcile a record by hand. Leave it out if you don't — nothing in the flow depends on it. Specifically, it does none of the following:
- It does not identify the patient. Deduplication keys on
patient_ref, so two patients can share an address — a parent and child on one family email are two records, exactly as they should be. - Appendix never sends to it. Nothing verifies the address belongs to the patient — you supplied it — so we don't email a person on the strength of it. The physician communicates with your user through your app.
- It is not a sign-in. It doesn't create an Appendix login and it isn't a password-reset target. Someone who later signs up at Appendix with the same address gets their own separate account, which has no access to the records you created.
When present it's checked for obvious typos (it has to look like an address), never for deliverability — nothing is ever sent to it. A replay that changes or omits it won't rewrite the stored value; the record keeps whatever you first sent.
Your app is the patient's channel
Because these patients have no Appendix login, the Appendix-hosted chat page can't serve them, and chat_url is not returned for developer-consented encounters at all — in the polling projection or in encounter.message webhooks. The doorbell still fires; only the link is absent.
Run the conversation inside your own app. Under full data visibility you read the physician's messages from GET /prescribing/encounters/{id}/details and post the patient's replies back with POST /prescribing/encounters/{id}/messages. That is the supported two-way channel for this flow — see Webhooks & polling.
2. Submit with patient_id
Call POST /prescribing/query with patient_id instead of the patient_* intake fields. The completeness gate works exactly as usual (iterate with session_token until final_decision_ready); once the letter is complete, the request submits directly for physician review — the response carries no consent_url.
curl -X POST https://api.appendix.com/api/v1/prescribing/query \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"query": "34F, 3 days of dysuria ...",
"patient_id": "6f2d...",
"external_id": "order_8842"
}'
{
"encounter_id": "b1a2...",
"status": "in_review",
"submission_id": "s_44c1...",
"final_decision_ready": true,
"next_steps": "Submitted for physician review. Track the outcome via GET /api/v1/prescribing/encounters or your outcome webhook."
}- Status vocabulary: pre-submission turns report
drafting(you'll never seeawaiting_consentorpending_identityon these encounters); after that the usualin_review→completed/canceledflow applies. - Outcomes arrive exactly like consent-flow requests: the signed outcome webhook plus
GET /prescribing/encounters. Rows for these encounters carryexternalConsent: trueand echo thepatientId. - Pricing is unchanged — outcome-based review fees from your prepaid credit balance, charged when the physician completes the review.
- If your account uses full data visibility, the details endpoint works for these encounters from submission onward — the consent your organization obtained covers sharing the care details back to you.
Enterprise end-to-end example →
All four calls in sequence — create the patient, submit the letter, read the physician conversation, and relay your patient's reply — with full request and response bodies.
Sandbox
Once Appendix enables this flow on your account, both endpoints work end to end with a test key: created patients are marked sandbox: true, and a complete submission short-circuits to a simulated decision — no physician, no charge — firing a sandbox: true outcome webhook so you can integration-test your handler. Sandbox patients only work with test keys, and production patients only with production keys.