Skip to content

Change Lead Status

Moves the lead to another status, and answers the lead together with the status it moved from.

Endpoint

PUT /v2/leads/{lead_id}/status

Path Parameters

Parameter Type Required Description
lead_id string Yes The lead.

Request Body

Parameter Type Required Description
status_id string Yes The status to move the lead to — an id from List Lead Status Definitions. Choosing the DROPPED-stage status drops the lead, as Drop Lead does.
reason_id string No A reason belonging to the status you're moving to. A reason marked needs_follow_up makes follow_up_date mandatory, except under the Dropped status.
subreason_id string Conditional A sub-reason belonging to the reason. Requires reason_id.
follow_up_date string (date) No YYYY-MM-DD. Required when the reason is marked needs_follow_up; ignored when the status is the DROPPED-stage one.
patient_type string No Corrects whether this is a new or a returning patient. One of NEW, RETURNING.
notes string No Free text recorded with the change.

Request

curl --location '{base_url}/v2/leads/3f8b21c4-5d9e-4a17-b6c2-0e7154a9d833/status' \
  --request PUT \
  --header 'Authorization: Bearer JWT_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "status_id": "c4a91f37-0b6e-4d28-8f15-6e3a2b9d7c42",
  "reason_id": "5e9a2c71-d84b-4f06-a3c9-0b7e1f6d2a55",
  "subreason_id": "a7d3f5b9-2c18-4e6a-9b40-8f1c5e2d7b63",
  "follow_up_date": "2026-10-02",
  "patient_type": "NEW",
  "notes": "Patient asked to be called back after 5pm."
}'

Response

Success Response

Code: 200 OK

{
  "lead": {
    "id": "3f8b21c4-5d9e-4a17-b6c2-0e7154a9d833",
    "organisation_id": "7412",
    "clinic_id": "5831",
    "patient_id": "63120",
    "case_id": "SPRY_CASE_6aabbdec586d1e1ac56a37fd",
    "case_title": "L Knee Post-Op",
    "patient_name": "Morgan Delgado",
    "patient_type": "NEW",
    "phone": "+1-555-0143",
    "email": "m.delgado@example.com",
    "date_of_birth": "1991-07-23",
    "status": {
      "stage": "IN_PROGRESS",
      "status_id": "c4a91f37-0b6e-4d28-8f15-6e3a2b9d7c42",
      "status_label": "Contacted",
      "reason_id": "5e9a2c71-d84b-4f06-a3c9-0b7e1f6d2a55",
      "reason_label": "Spoke with patient",
      "subreason_id": "a7d3f5b9-2c18-4e6a-9b40-8f1c5e2d7b63",
      "subreason_label": "Interested, deciding",
      "notes": "Patient asked to be called back after 5pm.",
      "follow_up_date": "2026-10-02",
      "changed_at": "2026-09-21T14:31:37Z",
      "drop_reason": null,
      "dropped_at": null
    },
    "lead_source": "MANUAL",
    "payment_mode": "INSURANCE",
    "complaint": "Pain in the left knee since surgery",
    "referring_physician_id": "3377",
    "intake_status": "INCOMPLETE",
    "eligibility_status": "PENDING",
    "authorization_status": "UNDETERMINED",
    "assigned_to_user_id": "2094",
    "appointment_id": null,
    "created_at": "2026-09-18T09:12:04Z",
    "updated_at": "2026-09-21T14:31:37Z"
  },
  "previous_status": {
    "stage": "IN_PROGRESS",
    "status_id": "8d2c5e0a-41f7-4b3e-9a6d-2f1b7c4e9a01",
    "status_label": "New Lead",
    "reason_id": null,
    "reason_label": null,
    "subreason_id": null,
    "subreason_label": null,
    "notes": null,
    "follow_up_date": null,
    "changed_at": null,
    "drop_reason": null,
    "dropped_at": null
  }
}

Response Fields

Field Type Description
lead object The updated lead. See Lead.
previous_status object The status the lead moved from — so a change can be read without keeping your own copy of every lead. See Previous Status.

Lead

Field Type Description
id string The lead id.
organisation_id string or null The organisation this record belongs to. Derived from the access token on writes and never trusted from the body.
clinic_id string or null The clinic the lead belongs to: the one its case was opened for, else the patient's. null when neither names one.
patient_id string or null The patient. Correlate on this — it's a stable id, and there's no external-reference field.
case_id string or null The lead's case — a spry_case_id. A case has exactly one lead, ever.
case_title string or null The title of the lead's case.
patient_name string or null The patient's first and last name.
patient_type string or null Whether this is a new or a returning patient. One of NEW, RETURNING.
phone string or null
email string or null
date_of_birth string (date) or null YYYY-MM-DD.
status object The lead's position in the pipeline: its stage, your organisation's status, the reason behind it, any follow-up date, and — once dropped — why and when. See Status.
lead_source string or null Where the lead came from: the source it was created with, MANUAL when none was given.
payment_mode string or null How this episode of care is paid for. UNKNOWN until the case or the patient's registration says. One of INSURANCE, SELF_PAY, UNKNOWN.
complaint string or null The patient's presenting complaint, in their words.
referring_physician_id string or null The case's primary referring physician.
intake_status string or null Progress through the intake forms the lead sent: N/A (none sent), PENDING (sent, not started), INCOMPLETE, COMPLETE.
eligibility_status string or null Where the insurance eligibility check for the lead's case stands.
authorization_status string or null Where the insurance authorization for the lead's case stands.
assigned_to_user_id string or null The staff member the lead is assigned to.
appointment_id string or null The appointment that converted the lead. null until it converts.
created_at string (date-time) or null When the lead was raised.
updated_at string (date-time) or null When the lead last changed.

Status

Field Type Description
stage string Where the lead is in the pipeline. Never set directly, and only moves forward: to IN_PROGRESS when the patient starts intake or the lead is given an in-progress status, CONVERTED when an appointment is booked against its case, DROPPED when it's dropped. It can run ahead of the status — a lead whose patient has started intake is IN_PROGRESS while its status is still the one it was raised on. One of NEW, IN_PROGRESS, CONVERTED, DROPPED.
status_id string or null Your organisation's own status, by its id in List Lead Status Definitions. The id stays the same when the status is renamed.
status_label string or null The status's name, as your organisation configured it.
reason_id string or null The reason behind the current status, by its id in your organisation's catalogue. On a dropped lead, the reason it was dropped for — one of the Dropped status's reasons — or null.
reason_label string or null The reason's name.
subreason_id string or null The sub-reason behind the current status, by its id.
subreason_label string or null The sub-reason's name.
notes string or null Free text recorded with the change.
follow_up_date string (date) or null When the lead is next due a follow-up. Cleared when it's dropped. YYYY-MM-DD.
changed_at string (date-time) or null When the status last changed.
drop_reason string or null Why the lead was dropped, as free text: the reason sent to Drop Lead (MANUAL when none was, including a drop that chose its reason by id), or STALE when it was dropped automatically, 31 days after it was raised. null unless it was dropped.
dropped_at string (date-time) or null When the lead was dropped. null unless it was.

Previous Status

Field Type Description
stage string Where the lead is in the pipeline. Never set directly, and only moves forward: to IN_PROGRESS when the patient starts intake or the lead is given an in-progress status, CONVERTED when an appointment is booked against its case, DROPPED when it's dropped. It can run ahead of the status — a lead whose patient has started intake is IN_PROGRESS while its status is still the one it was raised on. One of NEW, IN_PROGRESS, CONVERTED, DROPPED.
status_id string or null Your organisation's own status, by its id in List Lead Status Definitions. The id stays the same when the status is renamed.
status_label string or null The status's name, as your organisation configured it.
reason_id string or null The reason behind the current status, by its id in your organisation's catalogue. On a dropped lead, the reason it was dropped for — one of the Dropped status's reasons — or null.
reason_label string or null The reason's name.
subreason_id string or null The sub-reason behind the current status, by its id.
subreason_label string or null The sub-reason's name.
notes string or null Free text recorded with the change.
follow_up_date string (date) or null When the lead is next due a follow-up. Cleared when it's dropped. YYYY-MM-DD.
changed_at string (date-time) or null When the status last changed.
drop_reason string or null Why the lead was dropped, as free text: the reason sent to Drop Lead (MANUAL when none was, including a drop that chose its reason by id), or STALE when it was dropped automatically, 31 days after it was raised. null unless it was dropped.
dropped_at string (date-time) or null When the lead was dropped. null unless it was.

Error Response

Code: 400 Bad Request

{
  "code": "bad_request",
  "message": "Validation failed",
  "errors": [
    {
      "field": "patient_id",
      "message": "must be a string"
    }
  ]
}

Every error has the same shape — a machine-readable code, a message, and an errors[] array that's empty when there's nothing field-specific to report. The HTTP status is authoritative.

Status code Meaning
400 Bad Request bad_request The request body or parameters failed validation. errors[] names the offending fields.
401 Unauthorized unauthorized The access token is missing, malformed or expired.
403 Forbidden forbidden The request references a resource outside the token's organisation or clinic scope.
404 Not Found not_found No such resource, or it's outside your scope.
409 Conflict conflict The record conflicts with existing state — see the endpoint's notes.
429 Too Many Requests rate_limited Rate limit exceeded. Back off and retry.
500 Internal Server Error internal_error Unexpected server error.
502 Bad Gateway upstream_error Upstream service failed or timed out.

Notes

  • Statuses are defined per organisation and named by id, which stays the same when a status is renamed — read List Lead Status Definitions rather than hard-coding a set.
  • Send the status's full detail each time: reason_id, subreason_id, notes and follow_up_date left out are cleared, not kept.
  • previous_status is what lets you interpret the change without keeping your own copy of every lead.
  • 400 when the reason needs a follow-up date and none was sent, or when the reason doesn't belong to the status. 409 once the lead is converted or dropped — both are terminal.
  • Choosing the DROPPED-stage status drops the lead, as Drop Lead does: the reason and sub-reason chosen under it are recorded, drop_reason is MANUAL, and a follow-up date is ignored. The CONVERTED-stage status can't be chosen here (400); booking an appointment against the lead's case puts the lead on it.
  • Emits the lead.updated webhook — lead.dropped when the status chosen is the DROPPED-stage one.