Skip to content

Get Lead History

The lead's audit trail, newest first.

Endpoint

GET /v2/leads/{lead_id}/history

Path Parameters

Parameter Type Required Description
lead_id string Yes The lead.

Query Parameters

Parameter Type Required Description
limit integer No Entries per page, 1–200. Defaults to 50.
cursor string No next_cursor from the previous page. Omit for the first page.

Request

curl --location '{base_url}/v2/leads/3f8b21c4-5d9e-4a17-b6c2-0e7154a9d833/history' \
  --header 'Authorization: Bearer JWT_TOKEN'

Response

Success Response

Code: 200 OK

{
  "data": [
    {
      "id": "90412",
      "event_type": "STATUS_CHANGED",
      "field": "status_id",
      "old_value": "8d2c5e0a-41f7-4b3e-9a6d-2f1b7c4e9a01",
      "new_value": "c4a91f37-0b6e-4d28-8f15-6e3a2b9d7c42",
      "old_label": "New Lead",
      "new_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.",
      "actor_type": "USER",
      "actor_user_id": "2094",
      "actor_name": "Dana Whitfield",
      "occurred_at": "2026-09-21T14:31:37Z"
    }
  ],
  "next_cursor": "90412"
}

Response Fields

Field Type Description
data array of object The page of entries, newest first. See Data.
next_cursor string Send as cursor for the next page — it's the id of the last entry returned. Absent on the last page.

Data

Field Type Description
id string The entry's id.
event_type string What happened — e.g. CREATED, STATUS_CHANGED, OUTREACH_LOGGED, INTAKE_UPDATED, CONVERTED, DROPPED. New types are added over time; treat the list as open.
field string or null The lead field the entry changed, when it records a field change.
old_value string or null The value before the change. For STATUS_CHANGED: the previous status id when field is status_id, the previous stage when it's lead_status — a stage the pipeline moved on its own.
new_value string or null The value after the change. For STATUS_CHANGED, the new status id or stage, as field says.
old_label string or null For a status change, the name the previous status had at the time. null otherwise.
new_label string or null For a status change, the name the new status had at the time. null otherwise.
reason_id string or null The reason cited with a status change.
reason_label string or null The reason's name at the time.
subreason_id string or null The sub-reason cited with a status change.
subreason_label string or null The sub-reason's name at the time.
notes string or null Free text recorded with the change.
actor_type string or null USER, or SYSTEM for entries the pipeline writes itself.
actor_user_id string or null The user who caused the entry. null for SYSTEM entries.
actor_name string or null The user's name as recorded at the time, so the trail survives a rename.
occurred_at string (date-time) When the entry was recorded.

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

  • Cursor-paginated: pass next_cursor back as cursor. It's absent on the last page.
  • A STATUS_CHANGED entry is either a status change — field is status_id, with the old and new status ids and, in old_label and new_label, the names they had then — or a stage the pipeline moved on its own, such as intake starting — field is lead_status, with the old and new stages.
  • The history records more than the webhooks emit: outreach, notes, eligibility and authorization are all here and fire no webhook, and intake progress fires lead.updated only when it moves the lead out of NEW.