Event Types & Sample Events¶
The events Spry can deliver to a webhook subscription, with sample payloads in the current 2026-06-11 minimized format. A single subscription can listen to any combination of these events.
event_type |
Fired when |
|---|---|
patient.created |
A patient is registered |
patient.updated |
A patient's profile is updated |
patient.discharged |
A patient is discharged (their status becomes DISCHARGED). Fires instead of patient.updated for that change. |
appointment.created |
An appointment is booked |
appointment.updated |
An appointment is modified (status change, reschedule, check-in) |
appointment.cancelled |
An appointment is cancelled |
case.created |
A patient case (plan of care) is opened |
case.updated |
A patient case is modified (insurance, referring physician, status, body parts, …) — excluding discharge, which fires case.discharged instead |
case.discharged |
A patient case is discharged (its treatment status becomes DISCHARGED). Fires instead of case.updated for that change. |
lead.created |
A lead is raised, which happens when a case is created for a patient |
lead.updated |
A lead's status changes, or it moves between stages — excluding a move into a terminal stage, which fires lead.dropped / lead.converted instead |
lead.dropped |
A lead is dropped — by Drop Lead, or automatically if still open 31 days after it was raised. Terminal — the case never gets another lead |
lead.converted |
An appointment is booked against the lead's case. Terminal |
soap.created |
A SOAP note is created for an appointment |
soap.updated |
A SOAP note is edited after creation, while still in progress (before completion) |
soap.completed |
A SOAP note is marked completed |
soap.deleted |
A SOAP note is deleted |
Each payload follows the common envelope. The minimized format carries only identifiers under data — no status and no PHI — look up the full record from the Spry API by id.
Patient Events¶
patient.created, patient.updated, and patient.discharged carry the patient identifier only.
patient.dischargedvspatient.updated: a patient discharge fires onlypatient.discharged, neverpatient.updated. Subscribe topatient.dischargedexplicitly if you want to be notified of patient discharges.
data Fields¶
| Field | Type | Description |
|---|---|---|
organisation_id |
integer | Owning organisation |
patient_id |
integer | Spry patient identifier — look the patient up via the Spry API |
Sample — patient.updated¶
{
"event_id": "evt_3d1fa7e8-1234-4567-89ab-cdef01234567",
"event_type": "patient.updated",
"api_version": "2026-06-11",
"timestamp": 1776249887,
"data": {
"organisation_id": 74,
"patient_id": 45741
}
}
Sample — patient.discharged¶
Same shape as patient.updated — only event_type differs. Fetch the patient from the Spry API to confirm its (now DISCHARGED) status.
{
"event_id": "evt_9a4c2e11-aaaa-bbbb-cccc-1234567890ab",
"event_type": "patient.discharged",
"api_version": "2026-06-11",
"timestamp": 1783058137,
"data": {
"organisation_id": 74,
"patient_id": 73265
}
}
Appointment Events¶
appointment.created, appointment.updated, and appointment.cancelled carry the appointment and related identifiers.
data Fields¶
| Field | Type | Description |
|---|---|---|
organisation_id |
integer | Owning organisation |
appointment_id |
integer | Spry appointment identifier — look the appointment up via the Spry API |
patient_id |
integer | Patient the appointment belongs to |
spry_case_id |
string | Linked plan-of-care case (SPRY_CASE_<id>) |
clinic_id |
integer | Clinic the appointment belongs to |
Sample — appointment.updated¶
{
"event_id": "evt_8f3a2b9c-1234-4567-89ab-cdef01234567",
"event_type": "appointment.updated",
"api_version": "2026-06-11",
"timestamp": 1776246130,
"data": {
"organisation_id": 74,
"appointment_id": 113191,
"patient_id": 45675,
"spry_case_id": "SPRY_CASE_69d778fa05e30511a1a2b282",
"clinic_id": 44
}
}
Fetch the appointment's current status from the Spry API using data.appointment_id. Appointment status values are: CONFIRMED, PATIENT_CHECKIN, IN_PROGRESS, COMPLETED, CANCELLED, NO_SHOW.
Case Events¶
A case is a patient's plan-of-care container — it ties a patient to a specialization, referring physician, insurance cards, ICD/CPT codes, and treatment status. case.created, case.updated, and case.discharged carry the case and patient identifiers.
case.dischargedvscase.updated: a discharge fires onlycase.discharged, nevercase.updated— the same way a cancellation fires onlyappointment.cancelled. Subscribe tocase.dischargedexplicitly if you want to be notified of discharges.
data Fields¶
| Field | Type | Description |
|---|---|---|
organisation_id |
integer | Owning organisation |
spry_case_id |
string | Canonical Spry case identifier (SPRY_CASE_<id>) — look the case up via the Spry API |
patient_id |
integer | Patient the case belongs to |
Sample — case.updated¶
{
"event_id": "evt_2c9f1a7b-aaaa-bbbb-cccc-1234567890ab",
"event_type": "case.updated",
"api_version": "2026-06-11",
"timestamp": 1781153619,
"data": {
"organisation_id": 74,
"spry_case_id": "SPRY_CASE_6a2a3ee88546243488bdd2e1",
"patient_id": 48998
}
}
Sample — case.discharged¶
Same shape as case.updated — only event_type differs. Fetch the case from the Spry API to confirm its (now DISCHARGED) treatment status.
{
"event_id": "evt_7b2e9d10-aaaa-bbbb-cccc-1234567890ab",
"event_type": "case.discharged",
"api_version": "2026-06-11",
"timestamp": 1781696608,
"data": {
"organisation_id": 74,
"spry_case_id": "SPRY_CASE_6a17ebbe7f9a807bc2fbce0a",
"patient_id": 27227
}
}
Lead Events¶
A lead is a prospective patient's journey from first contact to a booked appointment. A lead belongs to exactly one case and a case has exactly one lead, ever. lead.created, lead.updated, lead.dropped and lead.converted carry the lead, patient, case and clinic identifiers.
Terminal events fire instead of
lead.updated: a lead being dropped or converted fires onlylead.droppedorlead.converted, the same way a discharge fires onlycase.discharged. Subscribe to them explicitly.Not every change to a lead is an event. Assignment, eligibility and authorization update the lead without emitting anything, and intake progress emits
lead.updatedonly when it moves the lead out ofNEW.lead.updatedtracks the status and the stage only — read Get Lead if you need the rest.
data Fields¶
| Field | Type | Description |
|---|---|---|
organisation_id |
integer | Owning organisation |
lead_id |
string | The lead (UUID) |
patient_id |
integer or null | The patient |
spry_case_id |
string or null | The lead's case. Null for a lead raised before cases owned leads, until one attaches |
clinic_id |
integer or null | Null when the case never named a clinic |
Sample — lead.converted¶
{
"event_id": "evt_bcf02f49-d4be-4219-9979-a7bfeb889150",
"event_type": "lead.converted",
"api_version": "2026-06-11",
"timestamp": 1789984697,
"data": {
"organisation_id": 1376,
"lead_id": "15d5e85a-d934-4791-9d48-4933311b1792",
"patient_id": 185781,
"spry_case_id": "SPRY_CASE_6aace0cf2e2a3b23cbb34ab4",
"clinic_id": 1467
}
}
Every lead event has this shape; only event_type differs. Read the lead from the Spry API with data.lead_id — the payload carries no status, so the record you fetch is always current.
SOAP Events¶
A SOAP context is the clinical-documentation record for an appointment — it tracks the subjective/objective/assessment/plan submissions, note type, completion and billing state, and the supervising/rendering/billing providers. soap.created, soap.updated, soap.completed, and soap.deleted all carry the same identifiers — only event_type differs.
data Fields¶
| Field | Type | Description |
|---|---|---|
organisation_id |
integer | Owning organisation |
soap_context_id |
string | Canonical SOAP-context id — look this up via the Spry API for the full note |
patient_id |
integer | Patient the note is for |
appointment_id |
integer | Appointment the note documents |
spry_case_id |
string | Case (SPRY_CASE_<id>) the note belongs to |
clinic_id |
integer | Clinic the note belongs to |
Sample — soap.created¶
{
"event_id": "evt_3f1c8a2d-aaaa-bbbb-cccc-1234567890ab",
"event_type": "soap.created",
"api_version": "2026-06-11",
"timestamp": 1782125075,
"data": {
"organisation_id": 1270,
"soap_context_id": "6a391213c356060e8fe73159",
"patient_id": 56751,
"appointment_id": 124775,
"spry_case_id": "SPRY_CASE_6a38fc1c4cedb3798667fa7a",
"clinic_id": 1333
}
}
No clinical content, status, or provider details leave Spry in a SOAP webhook payload. For
soap.deleted, the ids describe the note that was removed — it will no longer resolve via the Spry API.
Test Webhook¶
A test webhook uses the same envelope but adds "test": true to the payload so you can ignore test deliveries in production code paths.