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.contentis the agent’s answer, in Markdown.usage.creditsis 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_busyand 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.