Skip to main content
TalkPilot talks to your systems at three points of a call. The payloads on this page are generated from the code that sends them (talkpilot-shared/docs/webhook-samples/, kept in sync by a test), so what you see here is what arrives.

Configuration

Post-call URL — set post_call_webhook_url on the agent; both call_started and call_ended are delivered there:
Or configure it in the Dashboard under Agenten > [Agent] > Webhook. Pre-call URL — bound to the phone number, not the agent. Contact support@talkpilot.io to set it.

Pre-call request

Sent before the agent greets the caller. Use it to look the caller up in your CRM and hand the agent variables for its prompt and greeting ({{var.name}}), or to route the call to another agent. Request body:
Respond with 200 and JSON within 3 seconds. Two shapes are accepted:
  • variables / dynamic_variables — become {{var.<name>}} in prompt and greeting and are echoed back as pre_call_variables in both events below.
  • agent_id / override_agent_id — optional: the UUID of another agent of your organization that should take the call instead.
An empty or non-JSON answer counts as a failure and is retried; after the last attempt the call proceeds without variables.

call_started

Sent once the call is set up, before the first sentence. No retries — treat it as a hint, not as a guarantee.

call_ended

Sent after the call ends, with the full transcript.

Transcript entries

arguments and content are JSON encoded as strings — parse them a second time if you need the fields. A user entry with ignored: true is not part of the conversation with the agent — the agent discarded the line, its language model never saw it. ignored_reason says why: during_greeting — spoken in the short pause before the greeting and discarded, usually before the recording starts; during_transfer — picked up during or after a transfer. More reasons may follow, so treat any unknown value as ignored as well. To show only the conversation with the agent (for example in a CRM note or a summary), skip these entries. total_turns counts them.
The webhook carries the raw call. The customer name, request and summary you see in the Dashboard are produced afterwards by post-processing; fetch them with the Calls API if you need them.

Verifying the signature

Every delivery is signed when TalkPilot has a webhook secret configured for your account (ask support for it). Headers: Verify over the raw request body exactly as received. The body is serialized deterministically (keys sorted, no whitespace, UTF-8 not escaped), so re-serializing a parsed payload the same way also works, but the raw body is the safe choice.
In n8n, enable Raw Body on the Webhook node — a body that n8n has already parsed and re-serialized produces a different signature. Test vector (signature_vector.json in the samples): with secret beispiel-webhook-secret, timestamp 1788776142 and the call_ended payload above serialized canonically, the signature is sha256=8470225fe8cb45c069f89a9eea963b3702764a670e542b314094ef57167d3525.

Best practices

  1. Respond with 200 quickly — process asynchronously; call_ended waits at most 10 seconds per attempt.
  2. Deduplicate on call_id — call_ended is retried up to three times, so a delivery can arrive twice.
  3. Verify the signature instead of relying on a secret in the URL.
  4. Catch up via the API — if your endpoint was down for all attempts, the delivery is lost; use the Calls API to backfill.
  5. Don’t rely on call_started for anything critical — it is not retried.