API guide
Read calls, website forms and leads into your own systems, update lead stages from your CRM, and get new calls pushed to you as they happen. Create keys under Clients → Downloads and API → API keys. A key can be read only, and can be limited to some clients.
Authentication
curl https://portal.calltrail.co.uk/api/v1/me \
-H "Authorization: Bearer ct_live_…"Keep keys secret. Up to 600 requests a minute per key; over that you'll get 429 and should retry shortly after.
Endpoints
| Request | What it does |
|---|---|
GET /api/v1/me | The agency, access level and client ids the key can reach. |
GET /api/v1/businesses | Clients the key can reach. |
GET /api/v1/calls | Calls, newest first. |
GET /api/v1/calls/:id | One call. |
GET /api/v1/forms | Website form enquiries, newest first. |
GET /api/v1/leads | Leads, most recently updated first. |
PATCH /api/v1/leads/:id | Change stage, value_pence or name. Read and write keys only. Stage changes are sent on to connected ad platforms as usual. |
GET /api/v1/hooks | Webhook subscriptions. |
POST /api/v1/hooks | Subscribe a URL to events (below). Read and write keys only. |
DELETE /api/v1/hooks/:id | Unsubscribe. |
Lists and paging
Lists take business_id, since and until (ISO 8601 times), and limit (up to 500, default 100). Each page returns next_cursor; pass it back as cursor for the next page until it'snull.
curl "https://portal.calltrail.co.uk/api/v1/calls?since=2026-10-01T00:00:00Z&limit=500" \
-H "Authorization: Bearer ct_live_…"
{ "data": [ …calls… ], "next_cursor": "MjAyNi0xMC0…" }A call
{
"id": "6f1c…",
"business_id": "2b7e…",
"started_at": "2026-10-30T14:05:09Z",
"caller": "+447700900123",
"number_called": "+442392000001",
"number_label": "Google Ads",
"outcome": "answered",
"talk_seconds": 184,
"summary": "Leak near the chimney… survey booked Thursday.",
"lead": { "id": "a91d…", "name": "Mrs Patel", "stage": "booked" },
"attribution": {
"confidence": "session_matched",
"channel": "paid_search", "source": "google", "campaign": "Roof repairs",
"ad_group": "Leaks", "keyword": "roof leak repair", "search": null,
"landing_page": "/roof-repairs"
},
"url": "https://portal.calltrail.co.uk/b/2b7e…/calls/6f1c…"
}attribution.confidence is session_matched when the call was tied to one website visit, otherwise the source comes from the number that was called. search is the person's exact search when the ad network passed it.
Webhooks
curl -X POST https://portal.calltrail.co.uk/api/v1/hooks \
-H "Authorization: Bearer ct_live_…" -H "Content-Type: application/json" \
-d '{"business_id":"2b7e…","url":"https://example.com/calltrail","events":["call.completed","form.submitted"]}'Events: call.completed, call.answered, call.missed, call.first, form.submitted, lead.qualified, lead.quoted, lead.booked, lead.lost.
Each delivery is a JSON POST with an X-Calltrail-Signature header: t=<unix time>,v1=<hex>, where the hex is HMAC-SHA256 of t.body using the signing_secret returned when you subscribed. Reply with any 2xx. Failures are retried for about half an hour; reply 410 to unsubscribe.
Errors
Errors look like {"error": {"code": "not_found", "message": "…"}} with the usual HTTP status: 400, 401, 403, 404, 429 or 5xx.