Harnix
Integrate

Conversations

List and read conversations, the history window.

The endpoints below are for when you're building your own chat UI instead of using the <harnix-chat> widget — they all authenticate with an end-user token (Authorization: Bearer <token>, see Authentication), not an API key.

List available agents

GET https://api.harnix.vn/v2/agents
Authorization: Bearer <token>
[{ "id": "b6b0f9b2-...", "name": "Support assistant" }]

Returns every active agent in the organization — a token isn't tied to a specific agent.

Start a new conversation

POST https://api.harnix.vn/v2/conversations
Authorization: Bearer <token>
Content-Type: application/json

{ "agent_id": "b6b0f9b2-..." }

Returns 201 with a ConversationRead: { id, agent_id, title, created_at, last_message_at }. title is null until something sets it later (the console lets you name conversations).

List conversations

GET https://api.harnix.vn/v2/conversations?agent_id=...&limit=20&before=...
Authorization: Bearer <token>

Only returns conversations belonging to the calling end-user — there's no way for one end-user to read another's conversation, even knowing its ID. Keyset pagination: use the previous page's next_before as the next page's before; limit maxes out at 50 (default 50).

{
  "items": [{ "id": "77fd...", "agent_id": "b6b0f9b2-...", "title": null, "created_at": "...", "last_message_at": "..." }],
  "next_before": "77fd..."
}

Read a conversation

GET https://api.harnix.vn/v2/conversations/{conversation_id}?before_seq=...
Authorization: Bearer <token>

Returns a ConversationDetail — the conversation's info plus up to 50 of its most recent messages (messages). Each message has a role (user or assistant), content, citations (only on assistant messages, or null), seq (increasing order within the conversation), and run_id (the run that produced this message, useful for streaming or review). Use before_seq to page further back.

pending_approval tells you whether the conversation is paused waiting for the user to confirm an action: null when it isn't, otherwise { run_id, expires_at, calls: [{ call_id, server_name, name, title, arguments }] } — the same content as the approval frame of the stream. Use it when the user reopens the page: rebuild the confirmation prompt from here and answer with POST /v2/runs/{run_id}/approval, no need to reopen the stream.

pending_question tells you whether the conversation is paused waiting for the user to answer questions (ask_user): null when it isn't, otherwise { run_id, call_id, expires_at, questions: [...] } — the same content as the question frame of the stream. Use it when the user reopens the page: reconstruct the question UI from here and answer via POST /v2/runs/{run_id}/answer or send a follow-up message without reopening the stream.

A conversation that isn't yours, or doesn't exist — same conversation_not_found (404) either way: the endpoint never confirms that someone else's conversation exists.

Send a message in a conversation

POST https://api.harnix.vn/v2/conversations/{conversation_id}/messages
Authorization: Bearer <token>
Idempotency-Key: 2f6a...   (recommended)
Content-Type: application/json

{ "content": "What's our refund policy?" }

202 Accepted with { run_id, message_id, conversation_id } — identical to POST /v2/chat, except the conversation is already fixed by the URL and the sender is the end-user holding the token, not an API key.

While the conversation has an action awaiting confirmation (pending_approval is not null), sending a new message returns 409 approval_pending — approve or decline that action first. Resending the very message that created the waiting run, with the same Idempotency-Key, still returns 202 with that run as usual.

In contrast, when the conversation has a question waiting for input (pending_question is not null), sending a new message does not fail: the new message is treated as the user's free-text answer to the question. The endpoint returns 202 with the same waiting run (without creating a new run or counting against the 3 active runs limit), records the message in the conversation, and resumes the run. Resending with the same Idempotency-Key returns the same run without duplicate messages.

The history window

The agent doesn't see the entire conversation history when it answers — only a recent window (configured per agent, see Build an agent). A very long conversation still reads back in full through this API; only what's fed into the model's context is limited.

Next

  • Streaming — follow the run_id you just got, live.
  • Idempotency & cancel — including how to approve actions or answer waiting questions.
  • Runs & traces — conversation history read through this API is not affected by your organization's trace retention setting.

On this page