Skip to content
AISARAISAR
Calls

Calls

Call completed

call.completed

Fires when an answered call ends. Carries the final call record including total talk time. Calls that were never answered emit call.missed instead. If the call was recorded, a separate call.recording_ready event follows once the recording has finished processing.

HTTP request

AISAR sends a signed POST request to your webhook_url:

http
POST {webhook_url}
Content-Type: application/json
X-AISAR-Signature: sha256=...

{
  "event": "call.completed",
  "event_id": "evt_01JXXXXXXXXXXXXXXXXXXXXX",
  "timestamp": "2026-06-06T12:02:38.000000Z",
  "company_id": 1,
  "data": {
    "call_id": 123,
    "direction": "inbound",
    "status": "completed",
    "from_number": "12025550187",
    "to_number": "12025550187",
    "contact_id": 42,
    "conversation_id": 100,
    "channel_id": 5,
    "external_call_id": "wacall_abc123",
    "duration_sec": 150,
    "started_at": "2026-06-06T12:00:00+00:00",
    "answered_at": "2026-06-06T12:00:08+00:00",
    "ended_at": "2026-06-06T12:02:38+00:00",
    "routing": {
      "scheme_id": 7,
      "scheme_name": "Основная линия",
      "ivr_selections": [
        { "menu_node_id": "n_menu", "digit": "2", "label": "Отдел продаж", "attempt": 2, "at": "2026-06-06T12:00:09+00:00" }
      ],
      "final_step": { "type": "ring_group", "node_id": "n_sales", "result": "offered", "team_ids": [3] },
      "answered_by": { "assignee_type": "operator", "user_id": 17 },
      "path": [
        { "seq": 1, "node_id": "n_hours", "type": "schedule", "result": "work", "at": "2026-06-06T12:00:00+00:00" },
        { "seq": 2, "node_id": "n_menu", "type": "ivr_menu", "result": "invalid", "attempt": 1, "digit": "9", "at": "2026-06-06T12:00:05+00:00" },
        { "seq": 3, "node_id": "n_menu", "type": "ivr_menu", "result": "digit", "digit": "2", "attempt": 2, "label": "Отдел продаж", "at": "2026-06-06T12:00:09+00:00" },
        { "seq": 4, "node_id": "n_sales", "type": "ring_group", "result": "offered", "attempt": 1, "team_ids": [3], "at": "2026-06-06T12:00:09+00:00" }
      ],
      "truncated": false
    }
  }
}

The X-AISAR-Signature header carries an HMAC-SHA256 signature of the request body — use it to verify the request came from AISAR.

Example payload

json
{
  "event": "call.completed",
  "event_id": "evt_01JXXXXXXXXXXXXXXXXXXXXX",
  "timestamp": "2026-06-06T12:02:38.000000Z",
  "company_id": 1,
  "data": {
    "call_id": 123,
    "direction": "inbound",
    "status": "completed",
    "from_number": "12025550187",
    "to_number": "12025550187",
    "contact_id": 42,
    "conversation_id": 100,
    "channel_id": 5,
    "external_call_id": "wacall_abc123",
    "duration_sec": 150,
    "started_at": "2026-06-06T12:00:00+00:00",
    "answered_at": "2026-06-06T12:00:08+00:00",
    "ended_at": "2026-06-06T12:02:38+00:00",
    "routing": {
      "scheme_id": 7,
      "scheme_name": "Основная линия",
      "ivr_selections": [
        { "menu_node_id": "n_menu", "digit": "2", "label": "Отдел продаж", "attempt": 2, "at": "2026-06-06T12:00:09+00:00" }
      ],
      "final_step": { "type": "ring_group", "node_id": "n_sales", "result": "offered", "team_ids": [3] },
      "answered_by": { "assignee_type": "operator", "user_id": 17 },
      "path": [
        { "seq": 1, "node_id": "n_hours", "type": "schedule", "result": "work", "at": "2026-06-06T12:00:00+00:00" },
        { "seq": 2, "node_id": "n_menu", "type": "ivr_menu", "result": "invalid", "attempt": 1, "digit": "9", "at": "2026-06-06T12:00:05+00:00" },
        { "seq": 3, "node_id": "n_menu", "type": "ivr_menu", "result": "digit", "digit": "2", "attempt": 2, "label": "Отдел продаж", "at": "2026-06-06T12:00:09+00:00" },
        { "seq": 4, "node_id": "n_sales", "type": "ring_group", "result": "offered", "attempt": 1, "team_ids": [3], "at": "2026-06-06T12:00:09+00:00" }
      ],
      "truncated": false
    }
  }
}

Payload fields

FieldTypeDescription
call_idintegerInternal call ID (stable across all lifecycle events of this call)
directionstringinbound (from contact) or outbound (placed by operator)
statusstringCall status: completed
from_numberstringCaller number. For inbound calls — the customer; for outbound — your WhatsApp Business number
to_numberstringCallee number. For inbound calls — your WhatsApp Business number; for outbound — the customer
contact_idinteger|nullContact ID
conversation_idinteger|nullConversation ID
channel_idintegerWhatsApp Business channel ID
external_call_idstring|nullProvider-specific call ID (WhatsApp/SIP)
duration_secintegerTalk time in seconds (from answer to hangup)
started_atstring|nullISO 8601 timestamp the call started ringing
answered_atstringISO 8601 timestamp the call connected
ended_atstringISO 8601 timestamp the call ended
routingobject|nullHow the call travelled through the inbound call scheme: menu presses, final step, who answered and the full path. null if the call did not go through a scheme
routing.scheme_idinteger|nullID of the scheme the call went through
routing.scheme_namestring|nullScheme name at the time of the call
routing.ivr_selectionsarrayAccepted voice-menu key presses, in order. Invalid presses and silence are not listed here, they appear in path. Empty array if there was no menu
routing.ivr_selections[].menu_node_idstring|nullMenu node identifier at the time of the call
routing.ivr_selections[].digitstring|nullThe pressed digit
routing.ivr_selections[].labelstring|nullMenu item label (the edge label in the scheme), if set
routing.ivr_selections[].attemptinteger|nullMenu attempt number, starting at 1 (the menu may repeat)
routing.ivr_selections[].atstring|nullTime of the press, ISO 8601
routing.final_stepobject|nullThe last meaningful routing step: ring_group, responsible_manager, queue, ai_agent, voicemail, transfer or ai_escalation. A hangup step is reported here only if nothing meaningful came before it. Same shape as a path item, without seq and at
routing.answered_byobject|nullWho answered: { assignee_type, user_id }. assignee_type is operator or ai_agent; user_id is set for an operator. null if nobody answered (always for call.missed)
routing.patharrayFull walk through the scheme, at most 50 steps. A step has seq (from 1), node_id (node identifier at the time of the call; null for steps outside the graph), type, result, at (ISO 8601) and optional digit, attempt, label, team_ids, operator_ids, reason, from_user_id, to_user_id. type and result pairs: schedule: work | off; client_check: known | new; play: played | skipped; ivr_menu: digit | invalid | no_input | skipped; ring_group: offered; responsible_manager: offered | no_target; queue: offered | timeout; ai_agent: offered | failed | escalated | no_answer; voicemail: offered; hangup: hangup (reason carries the cause); transfer: transferred (from_user_id, to_user_id); ai_escalation: handed_to_operator (to_user_id)
routing.truncatedbooleantrue if the path hit the 50-step ceiling and later steps were not recorded