Leads
The voice agent captures a lead whenever a visitor explicitly provides their contact details (name, email, phone, plus any custom fields configured for the site). Use these endpoints to pull captured leads into your CRM.
Auth: API Key. Every endpoint is scoped to the key’s site.
List leads
GET /v1/public/leads?limit=25&status=new&since=2026-04-01T00:00:00ZAuthorization: Bearer sk_live_...Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
limit | int | 25 | 1–100 |
cursor | string | — | opaque cursor from a previous response (next_cursor) |
status | enum | — | new / contacted / qualified / disqualified |
since | ISO 8601 | — | created_at >= since |
Response
{ "data": [ { "id": "01J...", "site_id": "0aa06d96-13fe-...", "session_id": "sess_xyz", "conversation_id": "conv_abc", "visitor_id": "v-123", "page_url": "https://example.com/contact", "name": "Sarah Patel", "phone": "+15555550199", "email": "sarah@example.com", "data": { "company": "Acme", "use_case": "consult" }, "status": "new", "notes": null, "created_at": "2026-05-07T12:00:00.000Z", "updated_at": "2026-05-07T12:00:00.000Z" } ], "next_cursor": "MjAyNi0wNS0wN1QxMjowMDowMC4wMDBafDAxSi4uLg", "has_more": false}Pagination
Cursor-based. If has_more is true, pass next_cursor on the next call to
get the next page. Cursors are stable under inserts (new leads do not shift
your cursor position).
# First pagecurl -H "Authorization: Bearer $KEY" \ "https://api.spelo.ai/v1/public/leads?limit=50"
# Next page (extract next_cursor from previous response)curl -H "Authorization: Bearer $KEY" \ "https://api.spelo.ai/v1/public/leads?limit=50&cursor=$NEXT"Fetch one lead
GET /v1/public/leads/{id}Authorization: Bearer sk_live_...Returns the same shape as a list item, wrapped in { data: ... }.
Update a lead
Update status and/or notes. Other fields are read-only.
PATCH /v1/public/leads/{id}Authorization: Bearer sk_live_...Content-Type: application/json
{ "status": "contacted", "notes": "Called at 2pm — they want a follow-up demo"}A successful PATCH fires the lead.updated webhook (if any subscriber on
this site listens for that event — see Webhooks).
Lead statuses
| Status | Meaning |
|---|---|
new | Just captured. Default. |
contacted | You have replied. |
qualified | They are a real opportunity. |
disqualified | Not a fit (spam, wrong region, etc.). |
These are advisory. The agent does not change status automatically — it’s yours to update from your CRM.
Custom fields
data is a JSON object containing whatever fields the site is configured to
capture beyond name/email/phone. The shape comes from site_configs.lead_capture_fields.
{ "data": { "company": "Acme", "case_type": "personal-injury", "preferred_contact": "phone" }}See also
- Conversations endpoints — the call that captured a lead
- Webhooks — push events instead of polling
- Connecting your CRM — recipes for Zapier, Make, n8n