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 handed-off conversation is closed.
{
"conversation_id": 8214,
"chatbot_id": 17,
"previous_status": "human_active",
"resolved_at": "2026-08-26T10:31:00.000Z"
}previous_status distinguishes the two endings:
human_active— an operator joined and finished the conversation.pending_handoff— it was resolved while still queued, so nobody ever picked it up.
A rising count of pending_handoff resolutions is a staffing signal, not a success metric.
handoff.resolved only fires for conversations that were actually in a handoff state. An ordinary conversation being resolved fires conversation.ended alone.