Call tracking integration
Your call platform keeps doing what it does. It just also tells us about each call: one webhook, one payload. We match the caller to your Keap contact and attribute the call by the number they dialed, so phone leads show up in your report next to your web leads.
Your webhook URL
It's on your setup page, under "Track phone calls too" — copy it from there. It looks like this:
https://t.myvitalassistant.com/call?a=YOUR_ACCOUNT&k=YOUR_KEY
The key in the URL is your account's ingest key. It can only submit data, never read any, but treat the URL like a password all the same.
The payload
POST JSON to your webhook URL, one call per request:
{
"external_id": "CAL-8842",
"started_at": "2026-08-01T14:32:00Z",
"caller": "+1 727 555 0101",
"dialed": "(813) 555-0200",
"duration_s": 184,
"disposition": "answered",
"source_platform": "callrail",
"source_hint": "google-brand",
"recording_url": "https://…",
"transcript": "…"
}
| Field | What it is |
|---|---|
| external_id required | Your platform's own id for the call. This is the dedupe key: retries and repeat deliveries of the same id are safe. |
| started_at required | When the call started, as ISO 8601 or unix seconds. |
| caller one of these two | The caller's number, any common format. We normalize it and match it against your Keap contacts. |
| dialed one of these two | The number they called. This is what attributes the call: you tell us once which tracking number belongs to which ad source, and every call to it is credited there. |
| duration_s | Call length in seconds. |
| disposition | answered, missed, or voicemail. |
| source_platform | Name of the sending platform, for your own reading later. |
| source_hint | If your platform already knows the call's marketing source (Marchex and CallRail often do), send it here. It takes precedence over the dialed-number mapping. |
| recording_url, transcript | Optional, stored with the call. |
Responses
| Status | Meaning |
|---|---|
| 200 | Stored. {"ok":true,"id":"CAL-8842"} |
| 400 | The payload is missing something; the body says exactly what. The raw payload is kept either way so nothing is lost while you fix the mapping. |
| 401 | Wrong or missing key. Re-copy the URL from your setup page. |
| 500 | Our storage hiccupped. Retry: it's safe, thanks to external_id dedupe. |
Try it from a terminal
curl -X POST "YOUR_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{
"external_id": "test-1",
"started_at": "2026-08-01T14:32:00Z",
"caller": "+17275550101",
"dialed": "+18135550200",
"duration_s": 60,
"disposition": "answered"
}'
The call appears on your dashboard's CALLS card after the next daily refresh.
Hooking up common platforms
- CallRail / CallTrackingMetrics / Marchex: each has a webhook or postback setting per call event. Point it at your URL and map their field names to ours — most of them line up nearly one to one.
- Zapier / Make / n8n: trigger on your platform's "call completed" event, add a Webhooks POST step with the JSON above, done. This is the route for platforms with no native webhook.
- No automation at all: export your call log as CSV — every platform can — and send it to us; we import it. Columns should cover the same fields as the payload.
The number-to-source map. Tracking numbers only attribute calls if we know what each one means: this number is on your Google ads, this one is on the truck. Send us your list once (number → source, and campaign if you have one) and we configure it on your account. Changing it later is one email.
Privacy
Caller numbers are used to match calls to your own Keap contacts and for nothing else. Recordings and transcripts are stored only if you send them. Everything lives in your account's partition and shows only on your token-protected dashboard.