API v2 Conversations

List and export conversations, read messages, retry replies, submit tool results, and manage message feedback.

Use these endpoints to read conversation history and work with API v2 messages. Every endpoint on this page requires Authorization: Bearer YOUR_API_KEY and access to {agentId}.

Conversation Scope

Read-only conversation endpoints default to source=api_v2. Set source=widget to return widget and Playground conversations; Playground rows are stored with the widget source. Set source=all to return API v2, widget, and Playground conversations. Results always remain limited to the authenticated account's agent. An invalid source value or more than one source query parameter returns 400 VALIDATION_INVALID_BODY. Chat continuation, retry, feedback, message listing, and per-user reads remain scoped to API v2 conversations.

Response Objects

Conversation summaries contain:

FieldTypeNotes
idstringPublic conversation reference ID.
titlestringFirst user message, truncated to 80 characters; New conversation when unavailable.
createdAtintegerUnix timestamp in seconds.
updatedAtintegerUnix timestamp in seconds.
userIdstring or nullEnd-user ID supplied through API v2 chat.
sourcestring or nullNormally api_v2 or widget. Playground conversations are stored as widget.
statusstringStored conversation status, or ongoing when no status is stored.

Message objects contain:

FieldTypeNotes
idstringNumeric database message ID serialized as a string.
rolestringassistant for assistant senders; otherwise user.
partsarrayOne { "type": "text", "text": "..." } part.
createdAtintegerUnix timestamp in seconds.
feedbackstring or nullpositive, negative, or null.
metadataany JSON valuePersisted message metadata.

Tool-type message rows are omitted from conversation transcripts and message lists.

List Conversations

Path: /api/v2/agents/{agentId}/conversations

GET /api/v2/agents/{agentId}/conversations

Authentication: Bearer API key with access to {agentId}.

QueryRequiredConstraints
limitNoInteger from 1 to 100; defaults to 20.
cursorNoOpaque cursor returned by the preceding page. Replay it unchanged.
sourceNoapi_v2 (default), widget, or all. It may appear only once.
curl 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/conversations?source=all&limit=20' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Success: 200 OK

{
  "data": [
    {
      "id": "b2mD4kL8pQ1sT6vX",
      "title": "Where is my order?",
      "createdAt": 1784332800,
      "updatedAt": 1784332860,
      "userId": "customer_123",
      "source": "api_v2",
      "status": "ongoing"
    }
  ],
  "pagination": {
    "cursor": null,
    "hasMore": false,
    "total": 1
  }
}

Invalid limits, cursors, source values, and duplicate source parameters return 400 VALIDATION_INVALID_BODY.

Export Conversations

Path: /api/v2/agents/{agentId}/conversations/export

GET /api/v2/agents/{agentId}/conversations/export

Authentication: Bearer API key with access to {agentId}.

QueryRequiredConstraints
limitNoInteger from 1 to 20; defaults to 20.
cursorNoOpaque cursor returned by the preceding page. Replay it unchanged.
sourceNoapi_v2 (default), widget, or all. It may appear only once.

Export uses the same conversation ordering and cursor contract as the list endpoint, but caps each page at 20 conversations. Each conversation includes all non-tool messages, ordered from oldest to newest.

curl 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/conversations/export?source=api_v2' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Success: 200 OK

{
  "data": [
    {
      "id": "b2mD4kL8pQ1sT6vX",
      "title": "Where is my order?",
      "createdAt": 1784332800,
      "updatedAt": 1784332860,
      "userId": "customer_123",
      "source": "api_v2",
      "status": "ongoing",
      "messages": [
        {
          "id": "122",
          "role": "user",
          "parts": [{ "type": "text", "text": "Where is my order?" }],
          "createdAt": 1784332800,
          "feedback": null,
          "metadata": null
        }
      ]
    }
  ],
  "pagination": {
    "cursor": null,
    "hasMore": false,
    "total": 1
  }
}

Get a Conversation

Path: /api/v2/agents/{agentId}/conversations/{conversationId}

GET /api/v2/agents/{agentId}/conversations/{conversationId}

Authentication: Bearer API key with access to {agentId}.

QueryRequiredConstraints
sourceNoapi_v2 (default), widget, or all. It may appear only once.

The response includes the entire non-tool transcript, ordered from oldest to newest. This endpoint is not cursor-paginated; use the message-list endpoint for paged access to API v2 messages.

Success: 200 OK

{
  "data": {
    "id": "b2mD4kL8pQ1sT6vX",
    "title": "Where is my order?",
    "createdAt": 1784332800,
    "updatedAt": 1784332860,
    "userId": "customer_123",
    "source": "api_v2",
    "status": "ongoing",
    "messages": [
      {
        "id": "122",
        "role": "user",
        "parts": [{ "type": "text", "text": "Where is my order?" }],
        "createdAt": 1784332800,
        "feedback": null,
        "metadata": null
      }
    ]
  },
  "pagination": {
    "cursor": null,
    "hasMore": false,
    "total": 1
  }
}

A missing conversation within the selected source returns 404 RESOURCE_NOT_FOUND.

List Messages

Path: /api/v2/agents/{agentId}/conversations/{conversationId}/messages

GET /api/v2/agents/{agentId}/conversations/{conversationId}/messages

Authentication: Bearer API key with access to {agentId}. The conversation must be an API v2 conversation.

QueryRequiredConstraints
limitNoInteger from 1 to 100; defaults to 20.
cursorNoOpaque cursor returned by the preceding page. Replay it unchanged.

Message cursors are the one v2 pagination cursor whose server-side ID component is validated as a numeric string because messages use bigint IDs. Every other paginated v2 resource validates UUID IDs. Treat both forms as opaque; never construct or decode cursors. Messages within each returned page are ordered from oldest to newest.

Success: 200 OK

{
  "data": [
    {
      "id": "122",
      "role": "user",
      "parts": [{ "type": "text", "text": "Where is my order?" }],
      "createdAt": 1784332800,
      "feedback": null,
      "metadata": null
    },
    {
      "id": "123",
      "role": "assistant",
      "parts": [{ "type": "text", "text": "Please share your order number." }],
      "createdAt": 1784332860,
      "feedback": "positive",
      "metadata": null
    }
  ],
  "pagination": {
    "cursor": null,
    "hasMore": false,
    "total": 2
  }
}

A missing API v2 conversation returns 404 RESOURCE_NOT_FOUND; invalid limits and cursors return 400 VALIDATION_INVALID_BODY.

Retry an Assistant Reply

Path: /api/v2/agents/{agentId}/conversations/{conversationId}/retry

POST /api/v2/agents/{agentId}/conversations/{conversationId}/retry

Authentication: Bearer API key with access to {agentId}. The conversation must be an API v2 conversation.

Body fieldRequiredType and constraints
messageIdYesString or number that converts to a positive integer. It must identify an AI assistant message in the conversation.
streamNoBoolean; defaults to true.

Retry deletes the preceding user message, the selected assistant reply, and every later message, then replays that user text to regenerate the reply. If regeneration fails to persist, the deleted rows are restored.

curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/conversations/b2mD4kL8pQ1sT6vX/retry' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"messageId":"123","stream":false}'

Success: 200 OK. With stream: true, the response is a Server-Sent Events stream using the same event format as chat. With stream: false, the response is:

{
  "data": {
    "id": "124",
    "role": "assistant",
    "parts": [{ "type": "text", "text": "Here is a regenerated answer." }],
    "metadata": {
      "conversationId": "b2mD4kL8pQ1sT6vX",
      "finishReason": "stop",
      "usage": { "credits": 1 }
    }
  }
}

Malformed JSON returns 400 VALIDATION_INVALID_JSON. Invalid bodies return 400 VALIDATION_INVALID_BODY. See CHAT_RETRY_MESSAGE_NOT_FOUND, CHAT_RETRY_NO_USER_MESSAGE, RESOURCE_NOT_FOUND, and INTERNAL_SERVER_ERROR in the error catalog.

Submit a Tool Result

Path: /api/v2/agents/{agentId}/conversations/{conversationId}/tool-result

POST /api/v2/agents/{agentId}/conversations/{conversationId}/tool-result

Authentication: Bearer API key with access to {agentId}.

Body fieldRequiredType and constraints
toolCallIdYesNonempty string.
outputYesAny JSON value.
{
  "toolCallId": "call_123",
  "output": { "available": true }
}

Response: A matching pending action is claimed once and returns the assistant continuation as text/event-stream. Unknown or expired calls return 404; a competing or conflicting result returns 409.

Set or Clear Message Feedback

Path: /api/v2/agents/{agentId}/conversations/{conversationId}/messages/{messageId}/feedback

PATCH /api/v2/agents/{agentId}/conversations/{conversationId}/messages/{messageId}/feedback

Authentication: Bearer API key with access to {agentId}. The conversation must be an API v2 conversation.

{messageId} must convert to a positive integer and must identify an AI assistant message in the specified conversation.

Body fieldRequiredType and constraints
feedbackYespositive, negative, or null. Use null to clear feedback.
curl -X PATCH 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/conversations/b2mD4kL8pQ1sT6vX/messages/123/feedback' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"feedback":"positive"}'

Success: 200 OK

{
  "data": {
    "id": "123",
    "role": "assistant",
    "parts": [{ "type": "text", "text": "Please share your order number." }],
    "createdAt": 1784332860,
    "feedback": "positive",
    "metadata": null
  }
}

Malformed JSON returns 400 VALIDATION_INVALID_JSON; an invalid body returns 400 VALIDATION_INVALID_BODY; a missing conversation returns 404 RESOURCE_NOT_FOUND; a missing message returns 404 RESOURCE_MESSAGE_NOT_FOUND; and a non-AI-assistant target returns 422 RESOURCE_MESSAGE_NOT_ASSISTANT.

List Conversations for a User

Path: /api/v2/agents/{agentId}/users/{userId}/conversations

GET /api/v2/agents/{agentId}/users/{userId}/conversations

Authentication: Bearer API key with access to {agentId}.

{userId} must be 1 to 128 characters and may contain only letters, numbers, ., _, and -.

QueryRequiredConstraints
limitNoInteger from 1 to 100; defaults to 20.
cursorNoOpaque cursor returned by the preceding page. Replay it unchanged.
sourceNoOmit it or use api_v2. widget and all return 400 VALIDATION_INVALID_BODY; duplicate or invalid values also return 400.

Only API v2 chat writes userId, so this endpoint returns API v2 conversations only. Its success response is the same paginated conversation-summary envelope as List Conversations.

curl 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/users/customer_123/conversations' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Success: 200 OK. Invalid user IDs, limits, cursors, or source usage return 400 VALIDATION_INVALID_BODY.