Create a chat session via handoff
/v2.1/chat/handofforg.permission.conversation.createorg.permission.message.createThe API key or user must hold at least one of them.
Import an existing external conversation into Kustomer chat by creating a session and persisting historical messages in one call.
Identity is supplied in the JSON body (customerId, optional trackingId), not
via a /c/ tracking JWT. Unlike customer SDK handoff
(POST /c/v2.1/chat/handoff), this API-token route does not require a tracking
JWT; optional trackingId may be supplied on the request (see
CreateChatHandoffRequest).
Messages are validated and sorted by date. The array must include at least
one inbound (direction: in) and one outbound (direction: out) message
(2–100 messages total). from is applied to all outbound messages. Optional
externalId is stored on the session custom attributes for linking back to the
external thread. When active is false, the session is created closed (and
CSAT may be offered when enabled for the org).
Historical messages are inserted without PubNub fan-out during import, then mirrored to CRM conversation messages.
Chat conversations
The server-side chat API lets your backend take part in Kustomer chat with a regular API key. It can open chat sessions for a customer, post messages as the customer, an agent or an assistant, show typing, import bot conversations and record satisfaction ratings.
A chat session is a Kustomer conversation on the chat channel, seen from the chat side. Its ID is the conversation ID, so the same conversation appears in the agent desktop and in the customer's chat widget or app, and you can read it with the conversations API too. Sessions are usually created by the chat SDKs when a customer starts a chat. These v2.1 endpoints do the same jobs from your server, for custom chat front ends, messaging bridges and bots that answer before a human does. Anything you post is delivered in realtime to the customer's open chat on every device.
A session stays active until the chat is ended or deleted. Listing with active=true returns only active sessions that have at least one message.
Identity: customerId and trackingId
These endpoints never use a chat key or a customer's chat login token. Every request names the customer in customerId, and Kustomer checks it against the session: a mismatch fails with 403. trackingId is the chat SDK's ID for a visitor's browser or device. It's optional, but when a session has one, any trackingId you send must match. Creating a session without one reuses the tracking ID from the customer's latest chat session, if there is one; handoff imports never set one.
Use a server-side API key with the roles each endpoint lists, never a chat key, which must hold only org.tracking.
Who a message is from
| Endpoint | Appears as |
|---|---|
POST /v2.1/chat/messages |
The customer (direction: in). Returns 202 Accepted; the message is processed asynchronously. |
POST /v2.1/chat/assistant/messages |
The customer, replying inside an assistant (bot) flow, so the assistant continues from where it is. |
POST /v2.1/chat/outbound/messages |
An agent: from is the Kustomer user ID. Add auto: true for bot or AI replies so they don't count as a human first response. |
POST /v2.1/chat/outbound/assistant/messages |
An assistant line, attributed to from. Send exactly one of body, meta.template or attachments. |
Message bodies are up to 10,240 characters. Typing indicators are ephemeral and never stored. Your service owns their lifecycle: sending a message doesn't hide one, so send typing: false when you're done, and resend typing: true about every three seconds for long answers.
Which endpoint to use
| To | Call |
|---|---|
| Open a chat for a customer, optionally starting an assistant | POST /v2.1/chat/sessions |
| Import a conversation your own bot already had | POST /v2.1/chat/handoff |
| List a customer's or visitor's chats | GET /v2.1/chat/sessions |
| Read a chat's messages | GET /v2.1/chat/sessions/{id}/messages |
| Post as the customer | POST /v2.1/chat/messages or, in an assistant flow, POST /v2.1/chat/assistant/messages |
| Post as an agent or bot | POST /v2.1/chat/outbound/messages |
| Post as an assistant | POST /v2.1/chat/outbound/assistant/messages |
| Show or hide typing | POST /v2.1/chat/outbound/typing |
| Record a CSAT rating or comment | PUT /v2.1/chat/satisfaction-responses/{id} |
A handoff takes 2 to 100 messages, including at least one inbound and one outbound, and sorts them by date; active: false creates the conversation already closed. When you pass assistant on session create, Kustomer posts the assistant's greeting, and if that fails the session is still created. Session lists are paginated, newest first by lastMessageAt, and don't include messages. The CSAT response must already exist, created by Kustomer for the chat's survey; this call fills it in, and sending answers marks it commented rather than rated.
Request body
application/jsonrequiredRequired. Kustomer customer ID. The session is created for this customer (no tracking token).
Required. When true, the conversation/session is created open; when false, it is created closed.
Required. Identifies the sender of outbound messages (for example user id, agent name, or system identifier). Applied to all outbound messages (direction: out) in the handoff.
Historical messages to import. Must include at least one inbound (direction: in) and one outbound (direction: out) message. Maximum 100 messages.
Optional external identifier associated with the session (stored in the session's custom.externalId attribute).
Custom attributes. Keys must use Kustomer custom-attribute suffix rules (for example orderNumStr, priorityStr, chatSourceTree).
Optional chat settings / widget brand id. When omitted, the org default brand from settings is used.
Optional language code applied to all imported messages.
Optional conversation substatus ObjectId. Treated as an open substatus when active is true, or a done substatus when active is false.
Optional tracking identity ObjectId to attach to the session. When omitted on the API-token route, Kustomer may reuse the customer's latest chat-session tracking id when one exists. The session may have no tracking identity only when that fallback finds none or the lookup fails — omitting the field does not by itself guarantee an untracked session.
Responses
Created chat session with imported handoff messages