---
doc_version: "1.0.0"
last_updated: "2026-07-14T15:00:57.718Z"
title: "Chat API Reference"
description: "Complete reference for the ChatbotIQ public chat API: streaming conversations with bots via Server-Sent Events (SSE)."
keywords: [Chat API, REST API, SSE, streaming, server-sent events, bot chat, ChatbotIQ API]
---

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](/how-to/use-the-chat-api/).

---

## Base URL

```
https://app.chatbotiq.eu/v1/public
```

---

## Stream chat

Send a message and receive a streaming response via Server-Sent Events (SSE).

### Endpoint

```
POST /v1/public/chat/stream
```

### Authentication

None required. The bot must be set to **Public** privacy mode.

### Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `bot_id` | UUID | Yes | The bot's unique identifier. Found in the Deploy 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

```bash
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

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

| `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

```json
{
  "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

```
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

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

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](/reference/bot-settings/); they are off by default and, when set, the more restrictive limit wins.

---

## Get widget configuration

Retrieve the configuration needed to render the widget for a specific bot.

### Endpoint

```
GET /v1/public/bots/{bot_id}/config
```

### Authentication

None required.

### 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

Retrieve the message history for an existing conversation.

### Endpoint

```
GET /v1/public/conversations/{conversation_id}/messages?session_id={session_id}
```

### 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

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

```json
{
  "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

- [Use the Chat API](/how-to/use-the-chat-api/) - practical guide with code examples
- [Bot Settings](/reference/bot-settings/) - configure rate limits and privacy mode

## Sitemap

Full documentation index: [sitemap.md](/sitemap.md) and [llms.txt](/llms.txt).
