AI Voice Agent Backend
Module 13 · ai · intermediate
normalize-call.js
// Normalize end-of-call webhooks. Ignore other events (call_started, status updates…).
const body = $input.first().json.body ?? {};
let call = null;
if (body.event === 'call_ended' || body.event === 'call_analyzed') {
// Retell: { event, call: { call_id, transcript, from_number, start_timestamp, end_timestamp } }
const c = body.call ?? {};
call = {
platform: 'retell', event: body.event, call_id: c.call_id, from_number: c.from_number ?? '',
transcript: c.transcript ?? '',
duration_sec: c.end_timestamp && c.start_timestamp ? Math.round((c.end_timestamp - c.start_timestamp) / 1000) : null,
};
} else if (body.message?.type === 'end-of-call-report') {
// Vapi: { message: { type: 'end-of-call-report', call: { id, customer: { number } }, artifact: { transcript }, durationSeconds } }
const m = body.message;
call = {
platform: 'vapi', event: m.type, call_id: m.call?.id, from_number: m.call?.customer?.number ?? m.customer?.number ?? '',
transcript: m.artifact?.transcript ?? m.transcript ?? '', duration_sec: m.durationSeconds ?? null,
};
}
// Retell sends both call_ended and call_analyzed; summarize once
if (!call || call.event === 'call_analyzed' || !call.transcript) return [];
return [{ json: { ...call, transcript: String(call.transcript).slice(0, 12000), received_at: DateTime.now().toISO() } }];