Chat API Reference
The public chat API lets you have streaming conversations with a ChatbotIQ bot programmatically. This is the same endpoint that powers the embedded widget.
For a practical guide with code examples, see Use the Chat API.
Base URL
Section titled “Base URL”https://app.chatbotiq.eu/v1/publicStream chat
Section titled “Stream chat”Send a message and receive a streaming response via Server-Sent Events (SSE).
Endpoint
Section titled “Endpoint”POST /v1/public/chat/streamAuthentication
Section titled “Authentication”None required. The bot must be set to Public privacy mode.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
bot_id | UUID | Yes | The bot’s unique identifier. Found in the Embed tab of the Playground. |
message | String | Yes | The user’s message / question. |
session_id | String | Yes | An anonymous session identifier. Use any unique string (e.g., UUID) to track the conversation session. |
conversation_id | String | No | The conversation ID returned from a previous response. Include this to continue an existing conversation. |
recaptcha_token | String | No | Google reCAPTCHA token for bot protection (if configured). |
image_data | String | No | Base64-encoded image data (without the data: prefix). For multimodal models only. |
image_media_type | String | No | MIME type of the image: image/jpeg, image/png, or image/webp. Required if image_data is provided. |
Example request
Section titled “Example request”curl -X POST https://app.chatbotiq.eu/v1/public/chat/stream \ -H "Content-Type: application/json" \ -d '{ "bot_id": "your-bot-id", "message": "How do I get started?", "session_id": "unique-session-id" }'Response
Section titled “Response”The response is a Server-Sent Events (SSE) stream. Each event is a line prefixed with data: followed by a JSON object. Every event carries a type discriminator.
Event types
Section titled “Event types”type | Shape | Description |
|---|---|---|
status | {"type":"status","stage":"retrieving"} | Progress hints (retrieving, then generating). Informational. |
content | {"type":"content","content":"text"} | A chunk of the answer. Concatenate the content fields to build the full response. |
replace | {"type":"replace","content":"full text"} | The answer was post-filtered. Discard prior content and replace it with this value. |
notice | {"type":"notice","code":"rag_unavailable","level":"warning","message_key":"..."} | A non-fatal warning (e.g. retrieval degraded). |
done | {"type":"done","conversation_id":"uuid","assistant_message_id":"uuid","citations":[...]} | End of stream. citations is present only when the bot has source citations enabled. |
error | {"type":"error","error":"code","message":"..."} | Generation failed or was blocked. Common codes: content_filtered, service_unavailable, internal_error. |
There is no token field and no boolean done field. The answer text is always in the content field of content (and replace) events, and conversation_id/citations appear only on the final done event.
Citation object
Section titled “Citation object”{ "page_title": "Getting Started", "source_url": "https://docs.example.com/start", "source_id": "…", "score": 0.92, "from_web_search": false}When the bot has links disabled (include_links_in_responses = false), source_url is returned as an empty string.
Example SSE stream
Section titled “Example SSE stream”data: {"type":"status","stage":"retrieving"}data: {"type":"status","stage":"generating"}data: {"type":"content","content":"To"}data: {"type":"content","content":" get started,"}data: {"type":"content","content":" you need to..."}data: {"type":"done","conversation_id":"abc-123","assistant_message_id":"def-456","citations":[{"page_title":"Getting Started","source_url":"https://docs.example.com/start","source_id":"…","score":0.92,"from_web_search":false}]}Error responses
Section titled “Error responses”Failures before the stream opens are HTTP status codes; failures after the stream has started arrive as an in-stream error event (the HTTP status is already 200).
| Status | Reason |
|---|---|
| 400 | Missing/invalid field, or a required reCAPTCHA token was not supplied. |
| 403 | Bot is not public, bot is inactive, origin not in the bot’s allowed domains, free trial expired, or reCAPTCHA verification failed. |
| 404 | Bot not found. |
| 429 | Rate limit exceeded (per-IP, and any per-bot limits). |
Insufficient workspace credits do not produce a 402; they surface mid-stream as {"type":"error","error":"service_unavailable"}.
Rate limiting
Section titled “Rate limiting”Public chat is rate-limited per client IP, per bot:
- Baseline (per IP): 15 messages per minute, 120 per hour.
- A workspace-level chat limit also applies (tied to the plan).
- Additional per-bot limits can be set in Bot Settings; they are off by default and, when set, the more restrictive limit wins.
Get widget configuration
Section titled “Get widget configuration”Retrieve the configuration needed to render the widget for a specific bot.
Endpoint
Section titled “Endpoint”GET /v1/public/bots/{bot_id}/configAuthentication
Section titled “Authentication”None required.
Response
Section titled “Response”| Field | Type | Description |
|---|---|---|
bot_id | UUID | The bot’s identifier. |
bot_name | String | The bot’s display name. |
widget_settings | Object | All widget customization settings (colors, placement, etc.). |
suggested_questions | Array of strings | Pre-configured suggested questions. |
show_suggested_questions | Boolean | Whether to display suggested questions. |
suggested_questions_count | Integer | How many suggestions to show. |
welcome_message | String or null | Initial greeting message. |
warning_message | String or null | Custom rate-limit warning. |
recaptcha_site_key | String or null | reCAPTCHA site key, if reCAPTCHA is enabled. |
include_links | Boolean | Whether links are included in responses. |
language | String | Bot’s response language code. |
mcp_url | String or null | MCP integration endpoint, if configured. |
handoff_enabled | Boolean | Whether human handoff is available. |
handoff_trigger | String | Handoff trigger mode: “button”, “auto”, or “both”. |
handoff_offline_message | String or null | Message shown when no agents are online. |
handoff_agent_label | String or null | Display label for the human agent. |
handoff_available | Boolean | Whether agents are currently online. |
allow_user_images | Boolean | Whether users can upload images. |
contact_form_enabled | Boolean | Whether the contact form is enabled. |
contact_form_trigger | String | Contact-form trigger mode. |
contact_form_fields | Array or null | Contact-form field definitions. |
contact_form_success_message | String or null | Message shown after a successful submission. |
contact_form_button_display | String | When to show the contact-form button (e.g. after_response). |
Get conversation history
Section titled “Get conversation history”Retrieve the message history for an existing conversation.
Endpoint
Section titled “Endpoint”GET /v1/public/conversations/{conversation_id}/messages?session_id={session_id}Query parameters
Section titled “Query parameters”| Field | Required | Description |
|---|---|---|
session_id | Yes | Must match the session that created the conversation (ownership check). |
after | No | Return only messages created after this message ID. Used for polling. |
Authentication
Section titled “Authentication”None required. The session_id must match the one used to create the conversation. This endpoint is itself rate-limited to 30 requests/minute per IP.
Response
Section titled “Response”{ "messages": [ { "id": "uuid", "role": "user", "content": "How do I get started?", "citations": null, "feedback": null, "image_preview": null, "created_at": "2026-03-30T12:00:00Z" }, { "id": "uuid", "role": "assistant", "content": "To get started, you need to...", "citations": [ { "page_title": "Getting Started", "source_url": "https://docs.example.com/start", "source_id": "…", "score": 0.92, "from_web_search": false } ], "feedback": "positive", "image_preview": null, "created_at": "2026-03-30T12:00:01Z" } ], "conversation_status": "open"}Related
Section titled “Related”- Use the Chat API — practical guide with code examples
- Bot Settings — configure rate limits and privacy mode