Skip to main content

Post-call webhook reference

When a call ends, Callaro fires a single post-call webhook to the URL you configure on the agent (and any custom webhooks you’ve added). The webhook fires after intelligent-prompt analysis completes, so the payload includes analysis results — not just the transcript and metadata. This page is the source of truth for:
  • The payload shape you receive
  • How to verify the HMAC v1 signature
  • Idempotency, retries, and the manual-retry button
  • Webhook secret rotation

Delivery guarantees

  • At-least-once. We retry transient failures up to 3 times automatically with exponential backoff. A failsafe sweeper job picks up sessions that somehow miss the dispatch path within the first 30 minutes.
  • Manual retry. From any Call detail → Webhooks tab, an operator can press Retry (up to 10 manual retries per webhook target, rate-limited to one retry per minute).
  • Ordered after analysis. When analysis prompts are attached, the webhook fires after analysis finishes. If analysis fails, the webhook still fires (with analysis_status: "failed" or "partial") — analysis is never a blocker.

Payload (schema_version: 2026-04-28)

Idempotency

Always dedupe on idempotency_key. Within a session, the same key is reused for retries (manual or automatic). Treat the receipt of a key you’ve already processed as a no-op. Use attempt_number and is_retry purely for observability — they are not sufficient for dedup on their own.

Payload size cap (1 MB)

We cap each delivery at ~1 MB. When over budget, fields are dropped in this priority order: transcript_json → tool_calls[*].result → analysis_results[*].raw_response → trace_summary. The fields dropped are listed in truncated_fields and payload_truncated is set to true. To fetch the full transcript when truncated, GET /api/v1/voice_sessions/{voice_session_id}/transcript.

Verifying the signature (HMAC v1)

Signing is optional. If you have not configured a secret, no signature headers are sent and the request goes out unsigned. When a secret is configured we send the following headers: Use X-Webhook-Signature-V1 for new integrations. The legacy header is kept identical to its pre-v1 shape so old handlers do not break when v1 is rolled out.

Verification example (Node)

Verification example (Python)

Rotating the secret

Use the Webhook signing section under Step 7 of the agent wizard:
  1. Enable signing — generate a fresh secret and configure your handler.
  2. Rotate — generates a new primary; the previous secret stays valid as a secondary. During this window, X-Webhook-Signature-V1 contains comma-separated entries (one per active secret) so verification with either secret succeeds.
  3. Finalize — drops the old secret. Only the new secret signs new requests.
  4. Disable — removes all secrets; webhooks ship unsigned.
Secret rotation takes effect immediately for in-flight deliveries; you do not need to re-publish the agent.

Test webhook

The agent settings include a Test webhook button. It sends a synthetic payload (is_test: true, voice_session_id: -1, idempotency_key: call.completed.test.primary) to your configured URL using the live signing secret. Use this to validate verification code before going live.