Skip to content
Docs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Agents and Chat

List your agents and chat with them through the Chatvox API, including continuing conversations and linking them to your own users.

The agent object

Field Type Description
id string The agent’s ID.
name string The agent’s name.
status string active or inactive. An agent becomes inactive when your team has more agents than your plan allows, and can’t answer messages until you upgrade or remove another agent.
created_at string When the agent was created.

Only agents that have finished setup are returned. A key with Selected agents access only sees those agents.

List agents

GET /api/v1/agents
curl https://my.chatvox.co/api/v1/agents \
  -H "Authorization: Bearer cvx_your_key"

Returns a paginated list of agents, newest first.

Get an agent

GET /api/v1/agents/{agent}
{
  "id": "019f80ad-e549-712d-bc26-3ab29ae2228c",
  "name": "Support agent",
  "status": "active",
  "created_at": "2026-07-20T17:58:27+00:00"
}

Send a message

POST /api/v1/agents/{agent}/messages

Sends a message to the agent and returns its reply. The agent uses its instructions, knowledge, and actions just like on your website.

Field Required Description
message Yes The user’s message, up to 4,000 characters.
conversation_id No Continue an existing conversation. Leave it out to start a new one.
external_user_id No Your own ID for the user, up to 255 characters. Saved when the conversation starts so you can find their conversations later.
curl -X POST https://my.chatvox.co/api/v1/agents/AGENT_ID/messages \
  -H "Authorization: Bearer cvx_your_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "What are your opening hours?", "external_user_id": "user-42"}'
const response = await fetch(
  `https://my.chatvox.co/api/v1/agents/${agentId}/messages`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CHATVOX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      message: "What are your opening hours?",
      conversation_id: conversationId ?? undefined,
    }),
  },
);

const { conversation, reply } = await response.json();
// Save conversation.id and send it with the next message.
use Illuminate\Support\Facades\Http;

$response = Http::withToken(env('CHATVOX_API_KEY'))
    ->post("https://my.chatvox.co/api/v1/agents/{$agentId}/messages", [
        'message' => 'What are your opening hours?',
        'conversation_id' => $conversationId, // null starts a new conversation
    ])
    ->throw()
    ->json();

$reply = $response['reply']['content'] ?? null;
$conversationId = $response['conversation']['id'];
import os
import requests

response = requests.post(
    f"https://my.chatvox.co/api/v1/agents/{agent_id}/messages",
    headers={"Authorization": f"Bearer {os.environ['CHATVOX_API_KEY']}"},
    json={"message": "What are your opening hours?", "conversation_id": conversation_id},
    timeout=60,
)
response.raise_for_status()
data = response.json()
conversation_id = data["conversation"]["id"]

The response is 201 Created:

{
  "conversation": {
    "id": "01a121f0-6be6-700e-bda0-9860a935556f",
    "agent_id": "019f80ad-e549-712d-bc26-3ab29ae2228c",
    "contact_id": null,
    "title": "New Chat",
    "state": "ai_active",
    "source": "api",
    "external_user_id": "user-42",
    "last_message_preview": "We're open Monday to Friday, 9am to 5pm.",
    "last_active_at": "2026-10-09T18:32:52+00:00",
    "created_at": "2026-10-09T18:32:46+00:00"
  },
  "reply": {
    "id": 726,
    "role": "assistant",
    "origin": "ai",
    "content": "We're open Monday to Friday, 9am to 5pm.",
    "created_at": "2026-10-09T18:32:52+00:00"
  },
  "usage": { "credits": 1 }
}
  • reply.content is the agent’s answer, in Markdown.
  • usage.credits is the number of credits the reply used.

Continue a conversation

Every message without a conversation_id starts a new conversation, and the agent won’t remember earlier messages. To keep the context, store the conversation.id from the first response, for example per user in your database, and send it with every following message:

{ "message": "And on weekends?", "conversation_id": "01a121f0-6be6-700e-bda0-9860a935556f" }

You can only continue conversations that were started through the API. Conversations from your website, Public Chat, or WhatsApp return 404.

Retry safely with an idempotency key

If a request times out, you can’t tell whether the agent already answered. Send an Idempotency-Key header with a unique value for each message, such as a UUID or your own message ID, and reuse it when you retry:

curl -X POST https://my.chatvox.co/api/v1/agents/AGENT_ID/messages \
  -H "Authorization: Bearer cvx_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5f0c8a1e-2b7d-4e9a-9c41-7d2e6b3a8f10" \
  -d '{"message": "What are your opening hours?"}'
  • If the first request finished, a retry with the same key returns the same response with the header Idempotent-Replayed: true. The message isn’t sent again and no extra credits are used.
  • If the first request is still running, the retry returns 409 idempotency_in_progress. Wait a few seconds and retry again.
  • If the first request failed, the key isn’t kept, so the retry sends the message normally.
  • Using the same key for a different message returns 422 idempotency_key_reused. Use a new key for every new message.
  • Keys can be up to 255 characters, belong to the API key that sent them, and are kept for 24 hours.

Good to know

  • Replies usually take a few seconds. Use a request timeout of at least 60 seconds.
  • Send one message at a time per conversation. A second message while the agent is still answering returns 409 conversation_busy and isn’t saved, so you can send it again once the reply arrives.
  • API conversations appear in your agent’s Logs with the source API.