Skip to main content
When a call hands off to a voice agent, Yotel publishes a stream of webhook events that mirror the AI’s lifecycle: started, ended, transferred, escalated, and conference changes. The four pre-existing call.* events (started, answered, ended, recording_ready) still fire — call.recording_ready gains a stereo flag when the call was AI-driven. This page is the reference for AI-call subscribers. For the global event catalogue and delivery mechanics see Webhooks overview and Event catalog.
AI events ride the same delivery infrastructure as every other event — same envelope, same signature scheme, same retry schedule. Adding ai_session.* is a pure additive change; existing handlers keep working.

Common envelope

Headers:
X-Yotel-Signature follows the Stripe shape: HMAC_SHA256(secret, f"{t}.{raw_body}"). A 5-min freshness window prevents replay. See Signature verification for verifier code.

Subscribing

Webhook subscriptions are managed from the dashboard, not the public API. Pick AI-session events with the wildcard ai_session.* to opt into the full stream:
Save the signing_secret from the response — it’s shown once.

Per-event reference

call.started

Pre-answer originate event. Fires for every call, AI or human. For AI campaigns, voice_agent_id is the resolved UUID.

call.answered

Fires on CHANNEL_ANSWER. answered_by_amd is Yotel’s AMD classification — "machine" calls still get connected to the AI; your AI service can decide whether to leave a message or hang up.

call.ended

Fires on CHANNEL_HANGUP. disposition is null if the AI never called set_disposition. For full AI lifecycle context see ai_session.ended (fires alongside this one for AI calls).

call.recording_ready

Fires when the WAV upload to GCS completes (typically +2-5s after hangup). stereo: true for AI calls (left=caller, right=AI); false for human-only calls.
The signed_url expires ~15 minutes after issue. For long-lived access, hit recording_url (the proxy endpoint) on demand — or pull the bytes promptly into your own storage.

ai_session.started

Fires when Yotel opens the audio fork to your voice agent. ws_url is the resolved URL (after override hierarchy).

ai_session.ended

Fires when the AI session terminates (transfer, hangup, error, or 30-min timeout). metadata carries the full audit log — every log invocation plus the final transfer/hangup metadata.
outcome is one of: transferred_agent, transferred_e164, transferred_sip_uri, hangup, error, timeout.

ai_session.transferred

Fires on a successful transfer verb. The AI’s leg drops; the caller is bridged to destination. ai_session.ended fires immediately after.

ai_session.escalated

Fires on request_supervisor invocation and again on supervisor claim. Subscribers should dedupe on event.id if they only want the terminal claim.

ai_session.conference_changed

Fires on every conference state transition (conference_start, add, remove, leave) and the supervisor verbs (whisper, barge, monitor_start, monitor_stop).
change is one of: started, added, removed, left, monitor_started, monitor_stopped, whisper, barge. actor is "ai", "supervisor", or "tenant_api".

Stereo recording flag

For AI-driven calls, RECORD_STEREO=true is set on the FreeSWITCH dialplan. The resulting WAV has two channels:
  • Left — the caller’s audio (PSTN side).
  • Right — the AI’s audio (synthesised TTS or pre-recorded URL payback returned over the WS).
Mono recordings are returned for human-only calls (no connect_voice_agent step). The stereo flag on call.recording_ready lets transcript/QA pipelines pick the right diarisation strategy without probing the file.

SDK signature verification

Both SDKs already ship a webhook helper — no new function for ai_session.*. The WebhookEventType union grew by 5 (and 1 field on RecordingReady); upgrade the SDK to get the new types.
Python
TypeScript

Retry & dead-letter

Inherited from the global delivery layer:
  • 3 retries with backoff 200ms → 2s → 20s.
  • After 3 failures the delivery is marked dead_lettered.
  • Replay manually via POST /api/v1/webhooks/deliveries/{id}/replay.
  • 2xx = success; 4xx (except 408/429) = no retry; 5xx + 408/429 retry.
See Retries for the full schedule.

See also