{"openapi":"3.1.0","info":{"title":"NezerCare Integration API","version":"1.0.0","summary":"Connect patient enrollment and clinical workflows to NezerCare.","description":"NezerCare is the patient-care layer between your healthcare platform and your clinical workflow, whether you run a telehealth service, a clinic or practice, or a platform that serves them.\n\n## Quick start\n\n1. Make sure your organization has signed its BAA (an owner or administrator signs it in Workforce → Settings). API keys, webhooks and every patient feature stay off until it's signed.\n2. Create a **sandbox API credential** in Workforce → Integrations.\n3. Send it on every request as `Authorization: Bearer nzh_sb_…`. To try requests by hand, import this file into Postman (or any OpenAPI client) and set the key there.\n4. Send a `patient.created` event with a new UUID and your external patient identifier.\n5. Sign that patient into the widget on your site with a short-lived identity token for the same external patient identifier.\n6. Subscribe your endpoint to `clinical_case.opened`. When a case arrives, send a `processed` update, then carry on through the clinical-case API.\n\nKeep API keys on your server. Rotate any credential that has been pasted into chat, logs, source control, or another untrusted location.\n\n## Environments\n\nSandbox and production are isolated. Sandbox keys begin with `nzh_sb_`; production keys begin with `nzh_prod_`. A key can access only the organization and environment that issued it. The reference currently lists NezerCare's hosted sandbox server and local development. The production server's address isn't listed here yet: ask your NezerCare contact for it.\n\n## Idempotency and ordering\n\nEvery lifecycle event, provider message, and case update carries a caller-generated UUID. Retry an uncertain request using the **same UUID and identical body**. Reusing the UUID with different content returns `409`. Case updates must use the consecutive `nextSequence` returned by the progress endpoint.\n\n## Errors and limits\n\nValidation errors return `400`; authentication failures return `401`; an organization without a signed BAA gets `403` with code `BAA_REQUIRED` on every call (don't retry it: sign the BAA, then call again); tenant-scoped missing resources return `404`; idempotency and ordering conflicts return `409`. Retry network errors and `5xx` responses with exponential backoff and jitter. Do not automatically retry most `4xx` responses. Rate limits aren't part of the public contract yet, but handle a future `429` and honor `Retry-After`.\n\n## Clinical boundary\n\nWebhook delivery confirms transport only. It never means a clinician reviewed the case. NezerCare has no appointment-booking API: if your clinical system schedules care, report it with a `scheduled` case update. Only an explicit `resolved` update closes a case.","contact":{"name":"NezerCare integration support"}},"servers":[{"url":"https://api.nezercare.com","description":"Sandbox"},{"url":"http://localhost:4000/api","description":"Local development"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Workflows","description":"The staff app's endpoints for building, testing and switching on the workflows the agent runs for signed-in patients. They need a Firebase workforce token with `integrations.manage`; changes need MFA. Environment API keys are not accepted. Test runs call your real connections with a sample patient but never message a patient."},{"name":"Patient lifecycle","description":"Enroll, update or cancel patients from your system of record. Use the REST route, or the webhook-compatible route if your platform can only send webhooks."},{"name":"Clinical cases","description":"Confirm processing, report clinical progress, send patient-visible messages, and explicitly resolve escalated cases."},{"name":"Conversations","description":"One ordered message thread for a clinical case or work item. Read messages after a sequence number, send a message from your system with a caller-generated `requestId`, and report delivery (`delivered`, `read` or `failed`). A conversation only carries messages: it can't resolve a case or make a care decision."},{"name":"Webhooks","description":"Events NezerCare sends to your endpoints. Add an endpoint in Workforce → Integrations; its signing secret is shown once.\n\nVerify `x-nezer-signature` against the **raw request bytes** before parsing JSON. Compute the lowercase hexadecimal HMAC-SHA256 of `<x-nezer-timestamp>.<raw-body>` using the endpoint signing secret and compare it to the value after `v1=` using a constant-time comparison. Reject stale timestamps and deduplicate by `x-nezer-event-id`.\n\nWorkflow calls to your own systems (Destinations) are signed too, with the environment's **widget signing secret**: `x-nezer-signature` is the HMAC-SHA256 of `<x-nezer-timestamp>.<METHOD> <path and query>\\n<raw body>`. `order_lookup.requested` below is the order lookup contract an \"Order status and tracking\" workflow holds your order system to.\n\nThe event catalog includes the clinical-case lifecycle plus `billing.usage_threshold_reached` and `subscription.updated`. `billing.usage_threshold_reached` is sent once each as use, in every environment, reaches 80%, 95% and 100% of the month's credits, with `threshold`, `creditsUsed`, `monthlyCredits`, `remaining` and `paused`. Subscription updates report lifecycle states such as `active`, `grace_period`, `restricted`, and `canceled`; grace expiry uses reason `PAYMENT_GRACE_PERIOD_EXPIRED`, and a paid invoice that follows a failed payment carries `recovered: true` (a first or ordinary monthly charge doesn't). Event bodies may contain protected health information and must not be written to ordinary logs.\n\nUntil the organization signs its BAA, clinical-case events are held (not dropped, and no attempt is used) and go out once it's signed. `billing.usage_threshold_reached` and `subscription.updated` are about your account and carry no patient data, so they're never held for the BAA."}],"paths":{"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows":{"get":{"tags":["Workflows"],"summary":"List workflows","description":"Every workflow and its versions, archived ones included (`archivedAt`). `everLive` says whether it has ever been switched on or run, which decides between Delete and Archive.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}},"post":{"tags":["Workflows"],"summary":"Create a workflow","description":"Its first version is a draft.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["stableKey","name","definition"],"properties":{"stableKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,79}$"},"name":{"type":"string","minLength":1,"maxLength":120},"definition":{"$ref":"#/components/schemas/WorkflowDefinition"}}}}}},"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/{profileId}":{"patch":{"tags":["Workflows"],"summary":"Rename a workflow","description":"Staff see the name; patients don't.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}},"delete":{"tags":["Workflows"],"summary":"Delete a workflow","description":"Only one that has never been live, with its drafts and their test results. Audited. One that has been live is refused with `409`: archive it instead.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/{profileId}/archive":{"post":{"tags":["Workflows"],"summary":"Archive a workflow","description":"For one that has been live: it's switched off, out of the list and never matched, with its versions and runs kept. Audited.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/{profileId}/restore":{"post":{"tags":["Workflows"],"summary":"Restore a workflow","description":"Brings an archived workflow back, still switched off. Audited.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/{profileId}/draft":{"post":{"tags":["Workflows"],"summary":"Create or reuse a draft","description":"Without interrupting the live version.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/{profileId}/deactivate":{"post":{"tags":["Workflows"],"summary":"Switch a workflow off","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/{profileId}/runs":{"get":{"tags":["Workflows"],"summary":"List recent runs","description":"Step by step: outcomes only, never values.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/versions/{versionId}":{"put":{"tags":["Workflows"],"summary":"Save a draft","description":"Saves the current draft revision.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["expectedRevision","definition"],"properties":{"expectedRevision":{"type":"integer","minimum":1},"definition":{"$ref":"#/components/schemas/WorkflowDefinition"}}}}}},"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}},"delete":{"tags":["Workflows"],"summary":"Discard a draft","description":"Discards the draft on top of a live (or last live) version; that version is untouched. Audited. A workflow's only draft is deleted with the workflow instead.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/versions/{versionId}/readiness":{"get":{"tags":["Workflows"],"summary":"Check readiness","description":"What still blocks switching this version on.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/versions/{versionId}/test":{"post":{"tags":["Workflows"],"summary":"Test a version","description":"Runs a saved version with a sample patient; returns the transcript and each step's request and response.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["expectedRevision","opening","replies"],"properties":{"expectedRevision":{"type":"integer","minimum":1},"opening":{"type":"string","minLength":1,"maxLength":2000,"example":"Where is my order?"},"replies":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":500},"example":["A10001"]},"patientEmail":{"type":"string","maxLength":200,"description":"The sample patient's email, for ownership checks and {{patient.email}}."},"patientId":{"type":"string","maxLength":200,"description":"Or the sample patient's ID in your system; also sent as {{patient.externalId}} (order lookups use it)."}}}}}},"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/organizations/{organizationId}/environments/{environmentId}/conversation-workflows/versions/{versionId}/activate":{"post":{"tags":["Workflows"],"summary":"Switch a version on","description":"Only a draft that passed a test within 24 hours.","security":[{"workforceAuth":[]}],"parameters":[{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"environmentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["expectedRevision"],"properties":{"expectedRevision":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Successful read or update."},"201":{"description":"Successful POST operation."},"400":{"description":"Invalid definition, or not ready to switch on."},"401":{"description":"Workforce authentication required."},"403":{"description":"Permission or MFA requirement not met, or (code BAA_REQUIRED) a test run would call a real Destination before the organization has signed its BAA."},"404":{"description":"Not found in the selected organization and environment."},"409":{"description":"Stale revision, duplicate key, a version that can no longer change, a workflow that has been live (archive it instead of deleting it), or an archived workflow (restore it before editing or switching it on)."}}}},"/client/patient-events":{"post":{"tags":["Patient lifecycle"],"operationId":"applyPatientLifecycleEvent","summary":"Submit a patient lifecycle event","description":"`patient.created` needs the patient's email and enrolls them into the active protocol named by `programKey` (or `protocolId`). With neither, it uses the environment's active protocol, only when exactly one is active. The external patient ID is stored only as a keyed hash.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatientLifecycleEvent"},"examples":{"create":{"summary":"Enroll a patient","value":{"eventId":"6987074c-f976-4b17-817d-a0f17dc3a6da","type":"patient.created","externalPatientId":"patient_12345","firstName":"Taylor","lastName":"Example","email":"taylor@example.com","dateOfBirth":"1990-06-15","programKey":"glp1-maintenance","checkInCadenceDays":7}},"update":{"summary":"Update a patient","value":{"eventId":"4a3b3472-70fd-48d8-a36b-d95173eac9c2","type":"patient.updated","externalPatientId":"patient_12345","email":"new-address@example.com"}},"cancel":{"summary":"Cancel a patient pathway","value":{"eventId":"61594921-0f40-4a0d-91ec-88517503485f","type":"patient.cancelled","externalPatientId":"patient_12345"}}}}}},"responses":{"202":{"description":"Event accepted or an identical retry recognized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedEvent"}}}},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/client/webhooks/patient-events":{"post":{"tags":["Patient lifecycle"],"operationId":"receivePatientLifecycleEvent","summary":"Submit a patient lifecycle event through the webhook-compatible route","description":"`patient.created` needs the patient's email and enrolls them into the active protocol named by `programKey` (or `protocolId`). With neither, it uses the environment's active protocol, only when exactly one is active. The external patient ID is stored only as a keyed hash.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatientLifecycleEvent"},"examples":{"create":{"summary":"Enroll a patient","value":{"eventId":"6987074c-f976-4b17-817d-a0f17dc3a6da","type":"patient.created","externalPatientId":"patient_12345","firstName":"Taylor","lastName":"Example","email":"taylor@example.com","dateOfBirth":"1990-06-15","programKey":"glp1-maintenance","checkInCadenceDays":7}},"update":{"summary":"Update a patient","value":{"eventId":"4a3b3472-70fd-48d8-a36b-d95173eac9c2","type":"patient.updated","externalPatientId":"patient_12345","email":"new-address@example.com"}},"cancel":{"summary":"Cancel a patient pathway","value":{"eventId":"61594921-0f40-4a0d-91ec-88517503485f","type":"patient.cancelled","externalPatientId":"patient_12345"}}}}}},"responses":{"202":{"description":"Event accepted or an identical retry recognized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedEvent"}}}},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/clinical-cases/{caseId}/progress":{"get":{"tags":["Clinical cases"],"operationId":"getClinicalCaseProgress","summary":"Read current external-care progress","description":"Use this endpoint to reconcile sequence conflicts and confirm the next accepted sequence. Transport delivery and provider processing are intentionally separate fields.","parameters":[{"name":"caseId","in":"path","required":true,"description":"The canonical UUID from the clinical_case.opened webhook. This is not the patient-facing NC-XXXXXXXX reference.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Current progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseProgress"},"example":{"caseId":"150d31aa-c9ed-4624-b516-8f7f354f0848","status":"awaiting_processing","sequence":0,"nextSequence":1,"confirmationOverdue":false,"transportDelivered":true,"externalReference":null}}}},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/clinical-cases/{caseId}/updates":{"post":{"tags":["Clinical cases"],"operationId":"updateClinicalCase","summary":"Report provider-workflow progress","description":"The first update must be `processed` at sequence 1. Later updates may report scheduling, clinician response, patient contact, or final resolution. Use the same updateId and identical body when retrying.","parameters":[{"name":"caseId","in":"path","required":true,"description":"The canonical UUID from the clinical_case.opened webhook. This is not the patient-facing NC-XXXXXXXX reference.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseUpdate"},"examples":{"processed":{"summary":"Provider workflow created","value":{"updateId":"d574b886-f658-43dc-a62a-6c66ef74682d","sequence":1,"status":"processed","externalReference":"provider-conversation-001"}},"scheduled":{"summary":"Appointment scheduled","value":{"updateId":"8bb876eb-c77e-4686-b8f0-e4f76333670a","sequence":2,"status":"scheduled","externalReference":"appointment-456","scheduledFor":"2026-09-08T14:30:00-04:00"}},"resolved":{"summary":"Case resolved","value":{"updateId":"947ea6c9-cdb3-48d7-874b-bfcd59b54e99","sequence":3,"status":"resolved","externalReference":"provider-conversation-001","resolutionOutcome":"provider_follow_up","resolutionNote":"Clinician reviewed the concern and provided follow-up guidance."}}}}}},"responses":{"200":{"description":"Progress recorded or an identical retry recognized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseUpdateResult"}}}},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/clinical-cases/{caseId}/messages":{"post":{"tags":["Clinical cases"],"operationId":"sendClinicalCaseMessage","summary":"Send a message to the patient","description":"The encrypted message appears in the patient's secure case conversation. Do not put internal clinical notes in this patient-visible field. The patient receives a privacy-safe email without the message body.","parameters":[{"name":"caseId","in":"path","required":true,"description":"The canonical UUID from the clinical_case.opened webhook. This is not the patient-facing NC-XXXXXXXX reference.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderMessage"},"example":{"messageId":"a321530a-f9fe-4435-8593-38eb75174854","message":"A clinician reviewed your concern. Have your symptoms changed today?","externalReference":"provider-message-456"}}}},"responses":{"200":{"description":"Message created or an identical retry recognized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderMessageResult"}}}},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/conversations/{conversationId}/messages":{"get":{"tags":["Conversations"],"operationId":"listConversationMessages","summary":"Read an ordered conversation","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"afterSequence","in":"query","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Messages ordered by ascending sequence."},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Conversations"],"operationId":"sendConversationMessage","summary":"Send an inbound external message","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationMessageInput"}}}},"responses":{"201":{"description":"Message created or identical retry recognized."},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/conversations/{conversationId}/messages/{messageId}/delivery":{"post":{"tags":["Conversations"],"operationId":"updateConversationMessageDelivery","summary":"Report external delivery state","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"messageId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDeliveryUpdate"}}}},"responses":{"201":{"description":"Delivery state recorded."},"400":{"description":"The request is malformed or violates the operation contract.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API credential is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"INVALID_API_CREDENTIAL","message":"API credential is invalid."}}}},"403":{"description":"The organization hasn't signed its BAA, so patient features (and API keys) are off. An owner or administrator signs it in Settings; it takes effect at once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"code":"BAA_REQUIRED","message":"Sign your BAA to turn on patient features. An owner or administrator can sign it in Settings."}}}},"404":{"description":"The resource is not accessible in this credential's environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The idempotency identifier was reused with different content, or an update is out of sequence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"orderLookupRequested":{"post":{"tags":["Webhooks"],"operationId":"orderLookupRequested","summary":"order_lookup.requested","description":"Sent by an active \"Order status and tracking\" workflow when a signed-in patient asks where their order is (English or Spanish), to your connection's address + the step's path (POST /orders/lookup in the template). Never sent for an anonymous visitor, a health question or an emergency, and never contains what the patient typed. One attempt; NezerCare waits up to 5 seconds (less if the connection says so). Answer 200 with an `orders` array, empty when there are none. Anything else (another status, no answer in time, or an answer that breaks the contract) makes the workflow say it couldn't check and offer the team; nothing is guessed.\n\nVerify `x-nezer-signature` with the environment's **widget signing secret**: the lowercase hex HMAC-SHA256 of `<x-nezer-timestamp>.<METHOD> <path and query>\\n<raw body>`, compared after `v1=` in constant time. Reject timestamps more than 5 minutes old.","parameters":[{"name":"x-nezer-timestamp","in":"header","required":true,"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Unix seconds."},{"name":"x-nezer-signature","in":"header","required":true,"schema":{"type":"string","pattern":"^v1=[a-f0-9]{64}$"},"description":"v1=<hex HMAC-SHA256 of timestamp + '.' + METHOD + ' ' + path and query + '\\n' + raw body>, keyed with the widget signing secret."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderLookupRequest"}}}},"responses":{"200":{"description":"The patient's orders (latest first, or with placedAt on each). At most three are shown.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderLookupResponse"},"examples":{"orders":{"summary":"Orders found","value":{"orders":[{"id":"TEST-1003","status":"shipped","statusLabel":"On its way","carrier":"UPS","trackingUrl":"https://www.ups.com/track?tracknum=1Z0000000000000000","estimatedDelivery":"2026-10-02","placedAt":"2026-09-25T15:04:00Z","items":[{"name":"Test Product A","quantity":1}]},{"id":"TEST-1001","status":"delivered","carrier":"USPS","placedAt":"2026-08-28T12:00:00Z"}]}},"none":{"summary":"No orders for this patient","value":{"orders":[]}}}}}}}}},"clinicalCaseOpened":{"post":{"tags":["Webhooks"],"operationId":"clinicalCaseOpenedWebhook","summary":"clinical_case.opened","description":"Return 2xx after durable receipt. Verify the raw-body signature and deduplicate by x-nezer-event-id before creating or associating a provider workflow.","parameters":[{"name":"x-nezer-event-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"x-nezer-event-type","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-signature","in":"header","required":true,"description":"v1=<hex HMAC-SHA256 of timestamp + '.' + raw request body>","schema":{"type":"string","pattern":"^v1=[a-f0-9]{64}$"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClinicalCaseOpenedEvent"}}}},"responses":{"200":{"description":"Durably received."}}}},"patientMessageCreated":{"post":{"tags":["Webhooks"],"operationId":"clinicalCasePatientMessageCreatedWebhook","summary":"clinical_case.patient_message_created","description":"Contains patient-authored clinical content. Verify, deduplicate, and route it without placing the body in ordinary application logs.","parameters":[{"name":"x-nezer-event-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"x-nezer-event-type","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-signature","in":"header","required":true,"description":"v1=<hex HMAC-SHA256 of timestamp + '.' + raw request body>","schema":{"type":"string","pattern":"^v1=[a-f0-9]{64}$"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatientMessageCreatedEvent"}}}},"responses":{"200":{"description":"Durably received."}}}},"clinicalCaseAcknowledged":{"post":{"tags":["Webhooks"],"operationId":"clinicalCaseAcknowledgedWebhook","summary":"clinical_case.acknowledged","description":"Sent when your team acknowledges a case in NezerCare. It isn't the same as your `processed` case update.","parameters":[{"name":"x-nezer-event-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"x-nezer-event-type","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-signature","in":"header","required":true,"description":"v1=<hex HMAC-SHA256 of timestamp + '.' + raw request body>","schema":{"type":"string","pattern":"^v1=[a-f0-9]{64}$"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClinicalCaseLifecycleEvent"}}}},"responses":{"200":{"description":"Durably received."}}}},"clinicalCaseResolved":{"post":{"tags":["Webhooks"],"operationId":"clinicalCaseResolvedWebhook","summary":"clinical_case.resolved","description":"Emitted when a case reaches its final resolved state. A late delivery can describe a case your integration has already processed; deduplicate by event ID.","parameters":[{"name":"x-nezer-event-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"x-nezer-event-type","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"x-nezer-signature","in":"header","required":true,"description":"v1=<hex HMAC-SHA256 of timestamp + '.' + raw request body>","schema":{"type":"string","pattern":"^v1=[a-f0-9]{64}$"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClinicalCaseLifecycleEvent"}}}},"responses":{"200":{"description":"Durably received."}}}}},"components":{"securitySchemes":{"workforceAuth":{"type":"http","scheme":"bearer","bearerFormat":"Firebase workforce ID token","description":"Workforce setup only. Requires integrations.manage; mutations require MFA. Not a NezerCare environment API key."},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"NezerCare environment API credential","description":"Paste the complete nzh_sb_… or nzh_prod_… credential. Do not include the word Bearer."}},"schemas":{"WorkflowDefinition":{"type":"object","required":["category","description","steps"],"description":"Steps run in order unless one says where to go next. Anything that changes an account (a non-GET call not marked readOnly) must come after a call that checks ownership and after a Confirm step; a call using anything the patient typed must check ownership. Both are enforced again while running.","properties":{"schema":{"type":"integer","enum":[2]},"category":{"type":"string","enum":["support","billing","scheduling","fulfillment"]},"description":{"type":"string","minLength":1,"maxLength":300,"example":"Tells a patient where their order is."},"triggerPhrases":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":60}},"excludePhrases":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":60}},"steps":{"type":"array","minItems":1,"maxItems":30,"items":{"oneOf":[{"type":"object","required":["id","type","variable","prompt","format"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"type":{"type":"string","enum":["ask"]},"next":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"variable":{"type":"string","pattern":"^[a-zA-Z][a-zA-Z0-9_]{0,39}$"},"prompt":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."},"format":{"type":"string","enum":["text","order_number","email","number","photos"],"description":"photos shows an upload button and saves how many files were added."},"label":{"type":"string","minLength":1,"maxLength":40,"example":"Medication","description":"Names the answer in the team's hand-off summary (\"Medication: …\"). Defaults to the variable name in words."}}},{"type":"object","required":["id","type","destinationStableKey","method","path","save","notFoundReply","errorReply"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"type":{"type":"string","enum":["call_api"]},"next":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"destinationStableKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,79}$"},"method":{"type":"string","enum":["GET","POST","PUT","PATCH","DELETE"]},"path":{"type":"string","maxLength":500,"example":"/orders/{{orderNumber}}","description":"Added to the connection's address; values are URL-encoded."},"body":{"type":"object","additionalProperties":true,"description":"JSON for non-GET calls, up to 8,000 characters. Credentials belong on the connection."},"readOnly":{"type":"boolean","description":"A non-GET call that only looks something up."},"select":{"type":"object","required":["listPath","matchPath","equals"],"properties":{"listPath":{"type":"string","maxLength":160,"description":"Dot path into the JSON response, like shipment.tracking."},"matchPath":{"type":"string","maxLength":160,"description":"Dot path into the JSON response, like shipment.tracking."},"equals":{"type":"string","minLength":1,"maxLength":200,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."}}},"save":{"type":"array","maxItems":20,"items":{"type":"object","required":["variable","path"],"properties":{"variable":{"type":"string","pattern":"^[a-zA-Z][a-zA-Z0-9_]{0,39}$"},"path":{"type":"string","maxLength":160,"description":"Dot path into the JSON response, like shipment.tracking."}}}},"ownership":{"type":"object","properties":{"emailPath":{"type":"string","maxLength":160,"description":"Dot path into the JSON response, like shipment.tracking."},"patientIdPath":{"type":"string","maxLength":160,"description":"Dot path into the JSON response, like shipment.tracking."}},"description":"Where the response names its patient. A record that isn't theirs reads as not found."},"contract":{"type":"string","enum":["orders_v1"],"description":"Hold the answer to the order lookup contract (OrderLookupResponse). An answer that breaks it is treated as a failed call; no orders is treated as not found; otherwise the patient sees their latest orders as cards, and orderCount and latestOrderStatus are saved. Can't be combined with select."},"notFoundReply":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."},"errorReply":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."}}},{"type":"object","required":["id","type","variable","operator","then","else"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"type":{"type":"string","enum":["condition"]},"next":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"variable":{"type":"string","pattern":"^[a-zA-Z][a-zA-Z0-9_]{0,39}$"},"operator":{"type":"string","enum":["equals","not_equals","contains","is_empty","is_not_empty"]},"value":{"type":"string","maxLength":200},"then":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"else":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."}}},{"type":"object","required":["id","type","prompt","declineReply"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"type":{"type":"string","enum":["confirm"]},"next":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"prompt":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."},"declineReply":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."}}},{"type":"object","required":["id","type","message"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"type":{"type":"string","enum":["reply"]},"next":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"message":{"type":"string","minLength":1,"maxLength":1000,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."}}},{"type":"object","required":["id","type","message"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"type":{"type":"string","enum":["hand_off"]},"next":{"type":"string","maxLength":40,"description":"Another step's id, or \"end\"."},"message":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."},"summary":{"type":"string","minLength":1,"maxLength":500,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."},"teamAsk":{"type":"string","minLength":1,"maxLength":300,"description":"May use {{variable}}, {{patient.email}}, {{patient.externalId}} and {{run.id}}."},"category":{"type":"string","enum":["support","billing","scheduling","fulfillment","clinical"],"description":"The team that gets it; defaults to the workflow's category. clinical is the care team (a refill request, for example). The patient isn't sent a second, generic acknowledgement after this step's message; staff see an internal summary of the patient's answers at the top of the conversation."}}}]}}}},"OrderLookupRequest":{"type":"object","required":["version","type","requestId","patient"],"description":"The template's body. A clinic may edit it in the builder; {{patient.externalId}} is the ID you enrolled the patient with (never what they typed).","properties":{"version":{"type":"integer","enum":[1]},"type":{"type":"string","enum":["order_lookup.requested"]},"requestId":{"type":"string","description":"The workflow run's id; the same for every call in one run."},"patient":{"type":"object","required":["externalId"],"properties":{"externalId":{"type":"string","example":"test-patient-1"}}}},"example":{"version":1,"type":"order_lookup.requested","requestId":"0f2c9a4e-3d7b-4c1e-9a55-000000000000","patient":{"externalId":"test-patient-1"}}},"OrderLookupResponse":{"type":"object","required":["orders"],"description":"Checked strictly: a wrong type, an unknown status or a malformed date makes the whole answer invalid. Fields not listed here are ignored. null means not given.","properties":{"orders":{"type":"array","maxItems":50,"items":{"$ref":"#/components/schemas/OrderLookupOrder"}}}},"OrderLookupOrder":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","minLength":1,"maxLength":64,"description":"Your order number, as the patient knows it. A string (not a number)."},"status":{"type":"string","enum":["processing","shipped","delivered","delayed","cancelled"]},"statusLabel":{"type":["string","null"],"maxLength":80,"description":"Shown instead of the widget's own word for the status, as written."},"carrier":{"type":["string","null"],"maxLength":60},"trackingUrl":{"type":["string","null"],"maxLength":2000,"description":"Shown as a Track package link only when it's https (and has no user name or password); otherwise dropped."},"estimatedDelivery":{"type":["string","null"],"description":"YYYY-MM-DD, or an ISO 8601 date-time with a time zone."},"placedAt":{"type":["string","null"],"description":"YYYY-MM-DD or ISO 8601. When every order has it, the widget sorts latest first; otherwise it keeps your order."},"items":{"type":["array","null"],"maxItems":20,"items":{"type":"object","required":["name","quantity"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"quantity":{"type":"integer","minimum":1,"maximum":999}}}}}},"ConversationMessageInput":{"type":"object","required":["requestId","message"],"properties":{"requestId":{"type":"string","format":"uuid"},"message":{"type":"string","minLength":1,"maxLength":10000},"externalMessageId":{"type":"string","maxLength":200},"attachments":{"type":"array","items":{"type":"object","required":["id","fileName","contentType","sha256"],"properties":{"id":{"type":"string","format":"uuid"},"fileName":{"type":"string","maxLength":200},"contentType":{"type":"string","maxLength":160},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}}}}}},"ConversationDeliveryUpdate":{"type":"object","required":["externalMessageId","status"],"properties":{"externalMessageId":{"type":"string","maxLength":200},"status":{"type":"string","enum":["delivered","read","failed"]},"errorCode":{"type":"string","maxLength":80}}},"Error":{"type":"object","required":["message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"nextSequence":{"type":"integer"}}},"PatientLifecycleEvent":{"type":"object","required":["eventId","type","externalPatientId"],"properties":{"eventId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["patient.created","patient.updated","patient.cancelled"]},"externalPatientId":{"type":"string","minLength":1,"maxLength":200},"firstName":{"type":"string","minLength":1,"maxLength":80},"lastName":{"type":"string","minLength":1,"maxLength":80},"dateOfBirth":{"type":"string","format":"date"},"phone":{"type":"string","minLength":7,"maxLength":30},"email":{"type":"string","format":"email","maxLength":254,"description":"Required for `patient.created`: check-ins are sent by email."},"protocolId":{"type":"string","format":"uuid","description":"Send this or `programKey`, not both."},"programKey":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$","description":"The protocol's program key, e.g. `glp1-maintenance`: the stable way to choose a protocol, set in Workforce → Protocols."},"checkInCadenceDays":{"type":"integer","minimum":1,"maximum":30}}},"AcceptedEvent":{"type":"object","required":["accepted","duplicate"],"properties":{"accepted":{"type":"boolean","const":true},"duplicate":{"type":"boolean"}}},"CaseProgress":{"type":"object","required":["caseId","status","sequence","nextSequence","confirmationOverdue","transportDelivered"],"properties":{"caseId":{"type":"string","format":"uuid"},"status":{"type":"string"},"sequence":{"type":"integer","minimum":0},"nextSequence":{"type":"integer","minimum":1},"confirmationOverdue":{"type":"boolean"},"confirmationDueAt":{"type":["string","null"],"format":"date-time"},"transportDelivered":{"type":"boolean"},"scheduledFor":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"externalReference":{"type":["string","null"]}}},"CaseUpdate":{"type":"object","required":["updateId","sequence","status","externalReference"],"properties":{"updateId":{"type":"string","format":"uuid"},"sequence":{"type":"integer","minimum":1,"maximum":1000000},"status":{"type":"string","enum":["processed","scheduled","clinician_responded","patient_contacted","resolved"]},"externalReference":{"type":"string","minLength":1,"maxLength":200},"scheduledFor":{"type":"string","format":"date-time"},"resolutionOutcome":{"type":"string","enum":["patient_contacted","provider_follow_up","medication_adjusted","emergency_referral","no_further_action","other"]},"resolutionNote":{"type":"string","minLength":10,"maxLength":2000}}},"CaseUpdateResult":{"type":"object","required":["caseId","updateId","sequence","status","duplicate"],"properties":{"caseId":{"type":"string","format":"uuid"},"updateId":{"type":"string","format":"uuid"},"sequence":{"type":"integer"},"status":{"type":"string"},"duplicate":{"type":"boolean"}}},"ProviderMessage":{"type":"object","required":["messageId","message","externalReference"],"properties":{"messageId":{"type":"string","format":"uuid"},"message":{"type":"string","minLength":1,"maxLength":4000},"externalReference":{"type":"string","minLength":1,"maxLength":200}}},"ProviderMessageResult":{"type":"object","required":["caseId","messageId","duplicate"],"properties":{"caseId":{"type":"string","format":"uuid"},"messageId":{"type":"string","format":"uuid"},"duplicate":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"WebhookEnvelope":{"type":"object","required":["id","type","createdAt","data"],"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","additionalProperties":true}}},"ClinicalCaseOpenedEvent":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"type":"string","const":"clinical_case.opened"},"data":{"type":"object","required":["caseId","patientId","priority","handoff"],"properties":{"caseId":{"type":"string","format":"uuid"},"patientId":{"type":"string","format":"uuid"},"priority":{"type":"string","enum":["emergency","urgent","routine"],"description":"`routine` when the only red flags asked for a routine follow-up (for example, a medicine that isn't working). A `staff_slack` case is `urgent`, or `emergency` when the teammate's request used NezerCare's emergency words."},"source":{"type":"string","enum":["check_in","patient_concern","staff_slack"],"description":"Where the case came from: a check-in the patient answered, a concern the patient raised in the widget, or `staff_slack`, a clinical request a teammate made of @Nezer in your Slack channel. A `staff_slack` case is raised by staff, not reported by the patient: `patientNotes` is empty, `symptomScores` is `{}`, and the teammate's words stay in NezerCare as an internal note on the case."},"patientNotes":{"type":["string","null"],"description":"What the patient wrote. Empty for a `staff_slack` case."},"symptomScores":{"type":"object","additionalProperties":{"type":"integer"},"description":"The answers, by question key. When `stoppedEarly` is true, only the questions answered before the check-in stopped are here; the rest were skipped, not answered 0."},"matchedRules":{"type":"array","items":{"type":"string"},"description":"Every red flag that matched, not only the worst: `score:<tier>:<question key>>=<n>` (or `<=<n>` on a scale where higher is better), `phrase:<phrase>` and `semantic_phrase:<phrase>` for the protocol's emergency phrases, and `emergency_terms:<kind>` for NezerCare's own emergency words in the patient's note (or, for a `staff_slack` case, in the teammate's request), and `staff_request:slack` on every case raised from Slack."},"stoppedEarly":{"type":"boolean","description":"True when an answer called for 911: the check-in stopped at emergency guidance and sent what had been answered at once."},"handoff":{"type":"object","properties":{"progressPath":{"type":"string"},"updatesPath":{"type":"string"},"messagesPath":{"type":"string"}}}}}}}]},"PatientMessageCreatedEvent":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"type":"string","const":"clinical_case.patient_message_created"},"data":{"type":"object","required":["caseId","messageId","patientId","message","sentAt"],"properties":{"caseId":{"type":"string","format":"uuid"},"messageId":{"type":"string","format":"uuid"},"patientId":{"type":"string","format":"uuid"},"sender":{"type":"string","const":"patient"},"message":{"type":"string"},"sentAt":{"type":"string","format":"date-time"},"replyPath":{"type":"string"}}}}}]},"ClinicalCaseLifecycleEvent":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"},{"type":"object","properties":{"type":{"type":"string","enum":["clinical_case.acknowledged","clinical_case.resolved"]},"data":{"type":"object","required":["caseId","patientId","status"],"properties":{"caseId":{"type":"string","format":"uuid"},"patientId":{"type":"string","format":"uuid"},"status":{"type":"string"},"resolutionOutcome":{"type":["string","null"]},"resolutionNote":{"type":["string","null"]}}}}}]}}}}