Skip to content

List Leads

Leads in your organisation, newest first.

Endpoint

GET /v2/leads

Query Parameters

Parameter Type Required Description
page integer No 1-based page number. Defaults to 1.
page_size integer No Results per page. Defaults to 25.
stage string No Filter by stage. One of NEW, IN_PROGRESS, CONVERTED, DROPPED.
status_id string No Filter by status: an id from List Lead Status Definitions.
clinic_id string No Filter by clinic. A token limited to specific clinics only ever sees its own.
patient_id string No Filter by patient.
case_id string No Returns the case's lead. A case has exactly one lead, so this matches at most one.

Request

curl --location '{base_url}/v2/leads' \
  --header 'Authorization: Bearer JWT_TOKEN'

Response

Success Response

Code: 200 OK

{
  "items": [
    {
      "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"
    }
  ],
  "page": 1,
  "page_size": 25,
  "total": 1,
  "total_pages": 1
}

Response Fields

Field Type Description
items array of object The page of results. See Items.
page integer 1-based page number.
page_size integer Results per page.
total integer Total results matching the query.
total_pages integer Total pages available.

Items

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.

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.
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

  • A lead has two vocabularies. Stage is fixed — NEW, IN_PROGRESS, CONVERTED, DROPPED — and only moves forward, never set directly. Status is your organisation's own label, with its own reasons and sub-reasons. The two can differ: a lead whose patient has started intake is IN_PROGRESS while its status is still the one it was raised on.
  • A lead belongs to exactly one case and a case has exactly one lead, ever — so ?case_id= addresses a lead as reliably as its own id.
  • Filters: stage, status_id, clinic_id, patient_id, case_id. Statuses are filtered by id: status_key is no longer accepted (400).