Events

Handoff events

handoff.requested and handoff.resolved — a visitor wanted a person.

handoff.requested

Fires when a visitor asks for a human, whether they tapped the handoff card or the agent offered it after failing to answer.

{
  "conversation_id": 8214,
  "chatbot_id": 17,
  "channel": "live_chat",
  "visitor": {
    "visitor_id": "v_9f21…",
    "name": "Ada Lovelace",
    "email": "[email protected]",
    "phone": null,
    "company": null,
    "message": "I need to change my order"
  },
  "requested_at": "2026-08-26T10:07:00.000Z"
}

channel is the field that matters. It is:

  • live_chat — someone is being paged and the visitor is waiting in the widget right now. This is urgent.
  • email — nobody is being paged. Either the workspace is outside its configured hours, or live chat is not on its plan. The visitor has been told a person will follow up, and is not sitting there waiting.

Treating both the same is the mistake this field exists to prevent: routing an email handoff to a pager wakes someone for a message that expects a reply tomorrow, and treating a live_chat one as an email leaves a visitor waiting in an open widget.

Every field under visitor can be null — which fields are collected is configured per agent.

handoff.resolved

Fires when a request for a person stops being open: an operator's live chat ends, an operator declines the request, or the conversation is closed while the request is still waiting.

{
  "conversation_id": 8214,
  "chatbot_id": 17,
  "previous_status": "pending_handoff",
  "resolved_at": "2026-08-26T10:31:00.000Z",
  "outcome": "declined"
}

outcome says how it ended. It is present only when nobody joined:

  • declined — an operator declined the request. The visitor was told that no one is free, and the AI carried on with them in the same conversation.
  • closed — the conversation was resolved, archived or ended by the visitor while the request was still waiting, so nobody ever picked it up. Fires for waiting requests of every kind, including ones where nobody was paged (channel: "email" on the request).
  • absent — an operator joined and finished the conversation. previous_status is human_active.

A rising count of declined and closed outcomes is a staffing signal, not a success metric.

One ending does not fire this event: when nobody joins within five minutes, the AI steps back in and tells the visitor so, but the request stays open in the Inbox — someone can still take it over — so there is nothing resolved to report yet. It fires when that request is eventually taken and finished, declined, or closed.

handoff.resolved only fires for conversations that asked for a person. An ordinary conversation being resolved fires conversation.ended alone.