Leads
Base address: https://zqawbbylldymdfzineqq.supabase.co/functions/v1/pro-api
| Method and path | Scope | Does |
|---|---|---|
GET /v1/leads | leads:read | List, sync or look up leads |
GET /v1/leads/{id} | leads:read | One lead |
POST /v1/leads/{id}/accept | leads:write | Accept (charges like the Accept button) |
POST /v1/leads/{id}/decline | leads:write | Decline any lead you have not accepted, free |
PATCH /v1/leads/{id} | leads:write | Status, job total, paid amount, external ids, note, follow-up date |
PUT /v1/leads/{id}/status | leads:write | Same as PATCH (for code written for other platforms) |
GET /v1/leads/{id}/timeline | leads:read | Every event on the lead, in order |
GET /v1/leads/{id}/messages | messages:read | See Messages |
POST /v1/leads/{id}/messages | messages:write | See Messages |
POST /v1/leads/{id}/credit-request | billing:write | See Charges and credits |
List
GET /v1/leads| Query | What it does |
|---|---|
| (none) | Your most recently changed leads, newest first. Good for Zapier polling. |
since (or updated_since) | Leads created or changed after this ISO time, oldest change first, with paging. Use for sync. |
cursor | The next_cursor from the last page. |
status | Only this status: delivered, contacted, appointment, hired, job_done, not_hired, unreachable. |
limit | 1 to 100. Default 100. |
phone, email | Leads whose contact you can see with this phone (any format) or email. |
external_id | system:value, for example servicetitan:12345. |
customer_id | All leads from one customer. |
{"leads":[...],"has_more":true,"next_cursor":"MjAyNi0xMC0yMlQxNjoyMDo0NS4wMDIrMDA6MDB8NmIxYy4uLg","next_since":"2026-10-22T16:20:45.002Z"}- With
sinceorcursor: whenhas_moreistrue, call again withcursor=next_cursoruntil it isfalse. Then savenext_sincefor your next sync. Declined leads are included (declined: true, no contact) so your system can close them. - Without
since:next_sinceis the time of the call, so you can switch tosincesyncing from there. - Lookups return up to 100 matches, newest first, with
has_more: false. Phone and email only match leads whose contact details you can already see.
Accept
POST /v1/leads/{id}/acceptReturns the full lead with contact details. Accepting twice is safe. It charges the lead price exactly as the app does, so only accept leads you mean to take. A lead you declined cannot be accepted.
Decline
POST /v1/leads/{id}/decline
Content-Type: application/json
{"reason":"too_far"}reason (optional): too_far, not_my_service, too_busy, job_too_small, job_too_large, other. Only direct and related leads you have not accepted can be declined (409 otherwise). Declining is free.
Update
PATCH /v1/leads/{id}
Content-Type: application/json
{
"status": "hired",
"job_total_cents": 185000,
"paid_cents": 0,
"reason": "booked for Tuesday",
"note": "Gate code 1234. Dog in yard.",
"external_ids": {"servicetitan": "88213", "jobber": null},
"follow_up_at": "2026-10-28T16:00:00Z"
}Send any of these fields; leave out what you are not changing.
| Field | Rules |
|---|---|
status | One of our statuses, or a name other software uses (scheduled, completed, invoice_paid, customer_cancel...) which we map for you. Forward moves only (409 otherwise). The lead must be accepted. |
job_total_cents, paid_cents | Whole cents, 0 to 100,000,000. The lead must be accepted. invoice_total_cents is accepted as another name for job_total_cents. |
reason | Up to 60 characters, saved with the status change. |
note | Your internal note, up to 2,000 characters. null or "" clears it. Customers never see it. |
external_ids | Your own ids: keys are lowercase letters, digits or _ (up to 30), values are text up to 100. Merged with what is there; null removes a key. Up to 10. |
follow_up_at | A future time within 400 days, or null to clear. Same as the follow-up date in the app. |
Returns the full lead. A status update never charges or refunds you. duplicate or spam is not a status: ask for a credit instead.
Timeline
GET /v1/leads/{id}/timeline{"events":[
{"type":"lead.received","at":"2026-10-22T16:04:11Z"},
{"type":"charge.created","at":"2026-10-22T16:04:11Z","charge_id":"chg_311","amount_cents":4500,"status":"pending"},
{"type":"lead.accepted","at":"2026-10-22T16:06:02Z"},
{"type":"message.sent","at":"2026-10-22T16:07:40Z","message_id":"msg_902"},
{"type":"lead.status","at":"2026-10-22T18:30:00Z","from":"delivered","to":"hired","source":"api","reason":"booked for Tuesday","job_total_cents":185000,"paid_cents":null,"note":null}
]}