A single dialer call could previously emit several callsUpdated webhooks in quick succession as Twilio sent the call status, recording, AMD result, transcript, and AI enrichment in separate writes. The same call could also leak Twilio’s dial-time ring duration into “contacted” metrics. This release addresses both:
- One event per meaningful change.
callsUpdatednow fires only when a field included in the public payload actually changes (phone,note,isIncoming,duration,personId,callStatus,outcome,occurredAt). Internal enrichment writes (recording, transcript, sentiment, AMD, AI summary) no longer trigger duplicate events. callStatusis a pure lifecycle value. Twilio terminal outcomes (no-answer,busy,failed,canceled) are surfaced throughoutcome, whilecallStatusreportscompleted. Any user-set outcome (e.g. “left voicemail”) still takes precedence. This is a payload-shape change — partner integrations that branch oncallStatus == "no-answer"should switch to checkingoutcome.- Unanswered Twilio calls no longer report ring time as duration. When a Twilio call ends with a terminal outcome and no user-set outcome,
durationis reported as0. Partner-API-logged calls keep the integrator-supplied duration. - Contact metrics ignore unanswered calls.
last_contacted_atandlast_conversation_atno longer move forward onno-answer/busy/failed/canceledcalls. - Timestamps are UTC ISO8601.
occurredAtandcreatedAton the call payload andeventCreatedon every webhook envelope (eventCreatednow includes millisecond precision:2026-05-14T17:39:00.123Z).