Call2MeStart free
Developers

Webhooks: call events delivered to your server

Receive call_started, call_ended, call_analyzed and transfer events from an agent, plus signed account-level events for sessions and balance. This page documents the two delivery paths as they actually behave.

Updated October 6, 2026

There are two webhook paths and they behave differently. Read the table before wiring anything:

Agent webhookAccount webhook
Set onthe agent (webhook_url)your account (PUT /v1/webhooks)
Eventscall lifecycle, underscores (call_ended)sessions and balance, dots (voice_session.ended)
SignaturenoneX-Call2Me-Signature: sha256=… (HMAC-SHA256)
Retriesnone — one POST, 10 s timeout3 attempts, 1 s / 2 s / 4 s
Delivery lognonewebhook_deliveries

An earlier version of this page described dotted event names, a 24-hour retry window, a failed-delivery queue, a replay screen and an event_id field. None of that exists. It was removed on 6 October 2026 after the delivery code was read line by line.

Agent webhooks

Setup

Set the webhook URL on the agent:

curl -X PATCH https://api.call2me.app/v1/agents/agent_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"webhook_url": "https://your-server.com/webhooks/call2me"}'

Or in the dashboard: Agents → Edit → Webhooks.

Event types

EventWhenTypical use
call_startedAgent joined the callMark the call live in your CRM
call_endedCall finished, any reasonLog duration and usage, then fetch the call via GET /v1/calls
call_analyzedPost-call analysis is readyStore the summary and extracted fields
call_transferredAgent handed the caller to a human numberUpdate queue state
agent_transferredCall moved to another AI agentCorrelate the two call records
external_transferCall pushed to an external SIP destinationAudit routing
transfer_failedA transfer was attempted and the target did not pick upAlert ops
transfer_call_endedThe transferred leg endedClose the ticket
function_calledThe agent invoked one of your custom functionsLog tool usage

Names use underscores. There is no separate transcript event. The webhook carries only a summary of the call (see below); the full turn-by-turn record and recording are available afterwards from GET /v1/calls.

Payload shape

Every agent event has the same three-key envelope; everything else is inside data. call_ended:

{
  "event": "call_ended",
  "timestamp": "2026-10-06T14:23:11.481",
  "data": {
    "room": "agent_abc123_ab12",
    "participant": "sip_905551234567",
    "duration_messages": 14,
    "duration_seconds": 134,
    "usage": { "llm_tokens": 1840, "stt_seconds": 75.4, "tts_chars": 570 }
  }
}

The other two lifecycle events:

  • call_started — data is {room, participant, agent_id}.
  • call_analyzed — data is {room, agent_id, analysis}; sent only when the agent has post-call extraction fields configured.

There is no call_id, transcript, recording_url, direction, from or to in these payloads. Correlate with the call record via room and fetch the details with GET /v1/calls. timestamp is ISO-8601 UTC (no Z suffix). Event-specific fields of the transfer and function events vary; treat anything beyond event, timestamp and data as absent.

Delivery: one attempt, no signature

The agent path is fire-and-forget. The platform POSTs once with a 10-second timeout; any response below 400 counts as delivered and anything else — including a timeout — is logged on our side and not retried. Your endpoint should therefore return 2xx fast and do its work asynchronously.

There is no signature header on agent webhooks. If you need to verify origin, use the account-level path below, or check the room against GET /v1/calls before acting on it.

Deliveries are not guaranteed to be unique; dedupe on data.room + event.

Post-call action webhooks

A webhook post-call action is a separate delivery with its own, flat payload (also unsigned, one attempt):

{
  "event": "post_call_action",
  "call_id": "call_xyz789",
  "agent_id": "agent_abc123",
  "analysis": { "customer_name": "Ada", "interest_level": "high" },
  "timestamp": "2026-10-06T14:23:20.000000+00:00"
}

Tenant-level webhooks (account events)

The events above are per-agent call events (set via PATCH /v1/agents/{id}). For account-level events — useful for headless and mobile integrations — register a single tenant webhook with your sk_ key:

curl -X PUT https://api.call2me.app/v1/webhooks \
  -H "Authorization: Bearer sk_call2me_your_key" \
  -d '{"webhook_url": "https://your-app.com/hooks/call2me"}'
# → { "webhook_url": "...", "webhook_secret": "a1b2c3..." }   (store the secret)

Two events are delivered here:

voice_session.ended — a headless/AI voice session finished:

{ "event": "voice_session.ended", "timestamp": "2026-07-07T10:00:00Z",
  "data": { "room_name": "agent_x_ab12", "agent_id": "agent_x",
            "external_user_id": "user_42", "duration_sec": 143.2,
            "cost_usd": 0.24, "ended_at": "2026-07-07T10:00:00Z" } }

wallet.low_balance — your balance dropped below the threshold (default $5), at most once per day:

{ "event": "wallet.low_balance", "timestamp": "2026-07-07T10:00:00Z",
  "data": { "balance_usd": 3.10, "threshold_usd": 5.0 } }

These are the signed and retried deliveries: X-Call2Me-Signature: sha256=<hex HMAC-SHA256 of the raw body>, three attempts with 1 s, 2 s and 4 s pauses, and every attempt logged to webhook_deliveries with its status code. The secret is the one returned by PUT /v1/webhooks; store it, it is not shown again. Agent webhooks (above) do not get this — the two paths share only the {event, timestamp, data} envelope.

What's next

Frequently asked

Q.Which events does an agent webhook send?

call_started, call_ended, call_analyzed, call_transferred, agent_transferred, external_transfer, transfer_failed, transfer_call_ended and function_called. Underscores, not dots. Payloads carry the LiveKit `room` name for correlation.

Q.Are agent webhooks retried or signed?

No. The agent path is fire-and-forget: one POST, a 10-second timeout, no retry and no signature header. If your endpoint is down the event is gone. Account-level webhooks (below) are the signed, retried path.

Q.Is there a failed-delivery queue or replay?

No. An earlier version of this page described a 24-hour retry window, a failed-delivery queue and a replay button. None of that exists; it was removed on 6 October 2026 after checking the delivery code. Account-level deliveries are logged to webhook_deliveries so you can see what failed, but nothing is replayed automatically.

ShareX / TwitterLinkedIn

Ready to ship?

Spin up your first agent in 5 minutes — $5 free credit.

An interpreter or a voice agent, billed by the minute.

Start with free credit and no card. You pay only while a call is running.