Skip to content
TriedDocs
Webhooks

chat_ended

Sent when a chat is ended through the API or closed after the chat agent's idle timeout.

chat_ended carries the finished chat with its full message history and cost. Analysis follows in chat_analyzed.

When it fires#

Once per chat, when it moves to ended:

  • You call PATCH /end-chat/:id or POST /end-chat/:id.
  • A website widget visitor ends the chat (/public/chat/:id/end).
  • No new message arrived for the chat agent's end_chat_after_silence_ms (default 1 hour, between 1 minute and 24 hours). The idle check runs about once a minute, so a chat can close up to a minute after its limit. In the dashboard this is End the chat after in the chat agent's settings.

Ending a chat that has already ended does not send a second event.

Which settings enable it#

  • chat_ended in the chat agent's webhook_events (on by default).
  • URL: the chat agent's webhook_url, else the workspace URL.
  • Timeout: the workspace timeout, else 10 s.

Payload#

{
  "event": "chat_ended",
  "chat": {
    "chat_id": "chat_2d7f1a4c8e0b3f6a9c5e1d42",
    "chat_agent_id": "chat_agent_0c4f8e2a6b1d3f5a7c9e2b40",
    "agent_name": "Receptionist (chat)",
    "chat_type": "api_chat",
    "channel": "widget",
    "chat_status": "ended",
    "retell_llm_dynamic_variables": {
      "business_name": "Bondi Dental"
    },
    "metadata": {
      "origin": "https://www.bondidental.com.au",
      "public_key_id": "pk_4b8e1d5a9c2f6e0a3d7b1c58"
    },
    "start_timestamp": 1760679000210,
    "end_timestamp": 1760679391020,
    "transcript": "Agent: Hi, I'm Ava from Bondi Dental. How can I help?\nUser: Are you open on Saturday?\nAgent: Yes, we're open Saturday from 9am to 1pm.\nUser: Great, thanks.\nAgent: You're welcome. Anything else I can help with?",
    "message_with_tool_calls": [
      { "role": "agent", "content": "Hi, I'm Ava from Bondi Dental. How can I help?", "created_timestamp": 1760679000845 },
      { "role": "user", "content": "Are you open on Saturday?", "created_timestamp": 1760679012100 },
      { "role": "agent", "content": "Yes, we're open Saturday from 9am to 1pm.", "created_timestamp": 1760679013320 },
      { "role": "user", "content": "Great, thanks.", "created_timestamp": 1760679030880 },
      { "role": "agent", "content": "You're welcome. Anything else I can help with?", "created_timestamp": 1760679031750 }
    ],
    "chat_analysis": null,
    "chat_cost": { "combined_cost": 0.01 }
  }
}

Fields#

The fields are the same as in chat_started. At this point:

Field Value
chat_status ended
end_timestamp When the chat ended, Unix ms
transcript, message_with_tool_calls The complete conversation
chat_cost.combined_cost Final cost in AUD
chat_analysis null. It arrives in chat_analyzed

How to respond#

Reply 2xx. The body is ignored. Retries: up to 3 (1 s, 2 s, 4 s).

Post-chat analysis starts after this delivery finishes, including retries. A slow handler here delays chat_analyzed.