API Reference
The Chatbot API lets external applications integrate with any chatbot you create. Each chatbot has its own API tokens that authenticate requests and determine which chatbot handles the conversation.
| Base URL | https://your-domain.com/api/v1 |
| Auth | Bearer token (API key) |
| Format | application/json |
Authentication
All API requests must include a valid API token. Tokens are scoped to a specific chatbot — each token can only communicate with the chatbot it was created for.
Option 1 — Authorization header (recommended)
httpAuthorization: Bearer veribox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Option 2 — X-API-Key header
httpX-API-Key: veribox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Security: API tokens are shown only once at creation. Store them in environment variables, never in source code. Tokens can be revoked at any time from the chatbot settings.
Plan requirement: The API platform is available on the Standard plan and above. Starter and Basic plans cannot create API tokens.
Managing Tokens
| Method | Endpoint | Description |
|---|---|---|
GET | /api/chatbots/:id/api-tokens | List all tokens |
POST | /api/chatbots/:id/api-tokens | Create a token |
DELETE | /api/chatbots/:id/api-tokens/:token_id | Revoke a token |
Quick Start
- Open your chatbot dashboard and go to the Platforms page.
- Add an API platform.
- Create a new API token and copy it (shown only once).
- Use the token in the
Authorizationheader of every request.
bashcurl -X POST https://your-domain.com/api/v1/chat \ -H "Authorization: Bearer veribox_your_token_here" \ -H "Content-Type: application/json" \ -d '{ "message": "Hello, what can you help me with?", "format": "markdown" }'
Endpoints
POST/v1/chat
Send a message and receive the full response at once. Best for simple integrations where streaming is not needed.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | The user message to send to the chatbot |
conversation_id | string | No | Continue an existing conversation. If omitted, a new one is created |
format | string | No | Response format: markdown (default), plain_text, or html |
external_user_id | string | No | Optional identifier to associate conversations per user in your system |
curl -X POST https://your-domain.com/api/v1/chat \ -H "Authorization: Bearer veribox_your_token" \ -H "Content-Type: application/json" \ -d '{ "message": "What are your business hours?", "format": "markdown", "external_user_id": "user_12345" }'
Response 200 OK
json{ "error": 0, "error_message": "", "data": { "message": "Our business hours are **Monday-Friday, 9am-6pm**.", "conversation_id": 42, "format": "markdown", "usage": { "prompt_tokens": 850, "completion_tokens": 120, "total_tokens": 970 } } }
POST/v1/chat/stream
Send a message and receive the response as a Server-Sent Events (SSE) stream. The response is delivered token-by-token as it is generated.
The request body is identical to /v1/chat. The response uses text/event-stream.
# -N disables output buffering so tokens print immediately curl -N -X POST https://your-domain.com/api/v1/chat/stream \ -H "Authorization: Bearer veribox_your_token" \ -H "Content-Type: application/json" \ -d '{"message": "Explain your return policy in detail.", "format": "markdown"}'
SSE response stream
data: {"type":"conversation","conversation_id":42}
data: {"type":"delta","content":"Our return"}
data: {"type":"delta","content":" policy allows"}
data: {"type":"delta","content":" returns within 30 days..."}
data: {"type":"formatted","content":"<p>Our return policy allows ...</p>","format":"html"}
data: [DONE]
Note: For
htmlandplain_textformats,deltaevents contain raw markdown chunks. A finalformattedevent is sent before[DONE]with the fully converted text.
POST/v1/conversations
Explicitly create a new conversation. Useful when you want to start a fresh conversation for a specific user session before sending any messages.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
external_user_id | string | No | Your system's user identifier — used to group conversations per user |
curl -X POST https://your-domain.com/api/v1/conversations \ -H "Authorization: Bearer veribox_your_token" \ -H "Content-Type: application/json" \ -d '{"external_user_id": "session_abc123"}'
Response 200 OK
json{ "error": 0, "error_message": "", "data": { "conversation_id": 99, "chatbot_id": "bot_xxxxxxxx", "status": "active", "created_at": "2026-03-05T10:00:00Z" } }
GET/v1/conversations/:conversation_id/messages
Retrieve all messages for a conversation. Only conversations belonging to the authenticated chatbot can be accessed.
curl https://your-domain.com/api/v1/conversations/42/messages \ -H "Authorization: Bearer veribox_your_token"
Response 200 OK
json{ "error": 0, "error_message": "", "data": { "messages": [ { "id": 1, "role": "user", "content": "What are your business hours?", "created_at": "2026-03-05T10:00:00Z" }, { "id": 2, "role": "assistant", "content": "Our business hours are **Monday-Friday, 9am-6pm**.", "created_at": "2026-03-05T10:00:01Z" } ] } }
Streaming (SSE)
The streaming endpoint uses Server-Sent Events (SSE). Each event is a line prefixed with data: .
Event Types
| Event | When sent | Fields |
|---|---|---|
conversation | First event | type, conversation_id |
waiting | During tool/RAG calls | type, content (progress message) |
delta | Each token chunk | type, content |
formatted | After last delta (non-markdown format) | type, content, format |
[DONE] | Stream complete | Literal string — no JSON |
Reading SSE in JavaScript
javascriptasync function streamChat(token, message) { const response = await fetch("https://your-domain.com/api/v1/chat/stream", { method: "POST", headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify({ message, format: "markdown" }), }); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() ?? ""; for (const line of lines) { if (!line.startsWith("data: ")) continue; const payload = line.slice(6).trim(); if (payload === "[DONE]") { console.log("Stream complete"); return; } const event = JSON.parse(payload); if (event.type === "delta") { process.stdout.write(event.content); // or append to DOM } else if (event.type === "conversation") { console.log("Conversation ID:", event.conversation_id); } } } }
Response Formats
The format field controls how the chatbot response text is delivered. The RAG engine always generates Markdown internally; the API converts it before returning.
| Value | Description | Example output |
|---|---|---|
markdown | Default. Returns raw Markdown as generated by the model | Our **business hours** are Monday-Friday. |
plain_text | Strips all Markdown formatting. For SMS, voice, or plain terminals | Our business hours are Monday-Friday. |
html | Converts Markdown to HTML. For embedding in web pages or emails | <p>Our <strong>business hours</strong> are Monday-Friday.</p> |
Streaming note: In streaming mode,
deltaevents always contain raw Markdown chunks regardless of format. Forhtmlorplain_text, the final converted text is delivered in theformattedevent just before[DONE].
Error Codes
All responses follow a standard envelope. A non-zero error field indicates a problem.
json{ "error": 1, "error_message": "Unauthorized: invalid or expired API token", "data": null }
| HTTP Status | error code | Cause |
|---|---|---|
| 200 | 0 | Success |
| 400 | 4 | Bad request — invalid JSON, missing required field, or invalid format value |
| 401 | 1 | Missing or invalid API token |
| 404 | 3 | Chatbot or conversation not found |
| 500 | 5 | Internal server error — RAG pipeline or LLM failure |