Skip to main content
The Feather conversation API is built around conversations — stateful sessions that track the full message history, context variables, and lifecycle for a single end-user interaction. Within a conversation you can send synchronous turns, stream tokens over SSE for real-time UIs, poll for operator replies during a human handoff, and retrieve a paginated transcript at any time. This guide walks through each operation with working examples.

Create a conversation

Open a conversation by binding an assistant and identifying the end user. Creating a conversation over the API always produces a chat, live session — channel and surface are assigned by Feather, not set by you.
Pass a context_variables object in the request body to seed the conversation with pre-known data — for example, {"customer_name": "Alex", "account_tier": "premium"}. These values are available to the assistant’s prompt and tools.

Send turns (synchronous)

For standard request/response flows, post a turn and wait for the full reply.
If session_status becomes waiting_for_human or awaiting_approval, stop sending turns and poll for messages (below) until it returns to active or the conversation closes. Set include_evidence: true on the request to receive the knowledge-base chunks used to generate the reply.

Stream turns (SSE)

For chat UIs where you want to render tokens as they arrive, use the streaming endpoint. It returns a Server-Sent Events stream with the same request body as the synchronous turn endpoint.
Example SSE stream:
Event types — branch on the SSE event: name, not on any field inside the payload:
Always handle the error event explicitly. If the stream closes without a complete event, assume the turn failed and surface an appropriate message.

Poll messages (for async channels and handoffs)

When your assistant is connected to an asynchronous channel (email, SMS) or the conversation is in a human handoff, poll for new messages rather than holding an open HTTP connection.
Pass since_seq=-1 on the first request to retrieve every message. On subsequent polls, pass the previous response’s next_seq to receive only new messages. Both AI replies and human-operator relays arrive on this stream during a handoff.
During a handoff, poll every 2–5 seconds while session_status is waiting_for_human. Once it returns to active, the operator has handed control back and you can resume turn-based messaging.

Close a conversation

Signal that the conversation is resolved by closing it. This finalizes the session for memory sync, extraction, and analytics.
A conversation must be closed before it can be deleted. Attempting to delete a live conversation returns a 409 Conflict.

Retrieve the transcript

Fetch a paginated list of messages in a conversation — useful for post-session review, debugging, or exporting logs.
Paginate by passing cursor=<next_cursor> and limit=<n>. When has_more is false, you’ve reached the end of the transcript. For a bulk, encrypted export across many conversations, use Export Conversations.

What’s next?

Conversations concept

Deep dive into the session model, status lifecycle, and thread keys.

Human-in-the-loop

Handle approvals and operator handoffs during a live conversation.