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
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 wildcardai_session.* to opt into the full stream:
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.
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.
supervisor_id | Phase |
|---|---|
null | Invocation — escalation enqueued, no human yet |
<uuid> | Claim — supervisor accepted from the dashboard |
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).
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 forai_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 also
- Voice agents quickstart
- Control API — verbs that produce these events.
- Event catalog — every event Yotel can publish.
- Signature verification — reference verifier implementations.

