API reference
All endpoints are mounted at /v1/modules/scaibot/ and authenticate with the standard ScaiGrid bearer token. Responses use ScaiGrid's standard envelope ({ "data": ... } for success, { "error": ... } for failures).
Bots#
GET /bots#
List bots in the caller's tenant.
1 2 | |
Query parameters: limit (1-100, default 20), cursor, status (active, draft, archived).
POST /bots#
Create a bot.
| Field | Required | Notes |
|---|---|---|
name |
yes | Human-readable name. |
slug |
yes | URL-safe, unique within tenant. |
model |
yes | Frontend model id (scailabs/poolnoodle-omni, etc.). |
display_name |
no | What the bot calls itself; defaults to name. |
welcome_message |
no | First message visitor sees. |
placeholder_text |
no | Input field placeholder. |
primary_color |
no | Hex; defaults to tenant theme. |
max_tokens_per_response |
no | Default 500. |
max_context_messages |
no | History window. Default 20. |
knowledge_enabled |
no | Default false. |
knowledge_mode |
no | managed (default if enabled) or linked. |
knowledge_collection_id |
when linked | ScaiMatrix collection id. |
knowledge_settings |
no | top_k, score_threshold, max_chunks_per_doc, deduplicate. |
Returns 201 Created with the new bot.
GET /bots/{bot_id}#
Fetch one bot's full config.
PUT /bots/{bot_id}#
Replace the bot's config. All editable fields above are settable here.
PATCH /bots/{bot_id}/status#
Move the bot between lifecycle states.
1 | |
DELETE /bots/{bot_id}#
Hard-delete the bot. Conversations are retained (anonymised). Cascades to knowledge, escalation rules, tone.
Embed tokens#
POST /bots/{bot_id}/embed-token#
Mint a short-lived token for the widget.
| Field | Notes |
|---|---|
ttl_seconds |
60 – 86400. Default 3600. |
visitor_id |
Optional; appears in analytics and conversation records. |
visitor_email |
Optional. |
visitor_name |
Optional. |
metadata |
Arbitrary JSON; carried through to the conversation. |
1 2 3 4 5 6 7 8 | |
GET /bots/{bot_id}/embed-info#
Public, unauthenticated. Returns the widget URL and basic display config — used by the widget at load time. Does not return a token.
DELETE /bots/{bot_id}/embed-token#
Revoke a token before its TTL expires. Body: { "token": "sbt_..." }.
Chat#
POST /chat#
Send a message in a conversation. Response is a Server-Sent Event stream.
1 2 3 4 5 6 7 8 | |
Events:
| Event | Payload |
|---|---|
start |
{ "conversation_id": "...", "message_id": "..." } |
token |
{ "delta": "..." } |
citation |
{ "marker": "1", "document_id": "...", "snippet": "..." } |
escalation |
{ "rule_id": "...", "action_type": "...", "message": "..." } |
done |
{ "total_tokens": 123, "latency_ms": 1450 } |
error |
{ "code": "...", "message": "..." } |
Omit conversation_id to start a new conversation; the start event contains the assigned id.
Query parameter include_system_prompt=true adds a system_prompt event at the start (admin only — requires scaibot:conversations:read).
Tone#
GET /bots/{bot_id}/tone#
Read current tone config.
PUT /bots/{bot_id}/tone#
Set tone. See Tone for fields.
POST /bots/{bot_id}/tone/preview#
Generate one non-streamed response with a proposed tone.
1 2 3 4 | |
Returns { "data": { "response": "...", "tokens": 84 } }.
Escalation#
GET /bots/{bot_id}/escalations#
List rules in priority order.
POST /bots/{bot_id}/escalations#
Create a rule. Body fields:
| Field | Notes |
|---|---|
name |
Human label. |
priority |
Higher fires first; default 50. |
trigger_type |
keyword, intent, sentiment, confidence, explicit. |
trigger_config |
Type-specific (see Escalation). |
action_type |
email, webhook, slack, scaiqueue. |
action_config |
Type-specific. |
message |
What the bot says when this rule fires. |
Returns 201 Created.
PUT /bots/{bot_id}/escalations/{rule_id}#
Replace a rule.
DELETE /bots/{bot_id}/escalations/{rule_id}#
Remove a rule. Returns 204 No Content.
POST /bots/{bot_id}/escalations/reorder#
Bulk-reorder priorities.
1 | |
Knowledge#
GET /bots/{bot_id}/documents#
List documents and their indexing status.
POST /bots/{bot_id}/documents#
Upload a document. Multipart form data: file (binary), name (string).
GET /bots/{bot_id}/documents/{doc_id}#
Fetch one document's metadata and status.
PUT /bots/{bot_id}/documents/{doc_id}#
Replace a document's file. Same multipart form as POST. Re-indexes.
DELETE /bots/{bot_id}/documents/{doc_id}#
Remove a document; chunks drop out of retrieval immediately.
Conversations#
GET /conversations#
List conversations.
Query parameters:
| Parameter | Notes |
|---|---|
bot_id |
Filter to one bot. |
visitor_id |
Filter to one visitor. |
status |
active, closed, escalated. |
since |
ISO 8601 timestamp. |
limit, cursor |
Pagination. |
GET /conversations/{conversation_id}#
Full transcript including all turns, citations, retrieved chunks, escalation events.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
PATCH /conversations/{conversation_id}/status#
Manually close a conversation.
1 | |
Errors#
All endpoints return ScaiGrid's standard error envelope:
1 2 3 4 5 6 7 8 | |
ScaiBot-specific codes:
| Code | Meaning |
|---|---|
BOT_NOT_FOUND |
Bot id doesn't exist (or you can't see it). |
BOT_SLUG_TAKEN |
Slug already in use within tenant. |
BOT_INVALID_MODEL |
Model id not available to your tenant. |
CONVERSATION_NOT_FOUND |
Conversation id doesn't exist or doesn't belong to this bot. |
EMBED_TOKEN_EXPIRED |
Token expired; mint a fresh one. |
EMBED_TOKEN_INVALID |
Token signature didn't verify. |
DOCUMENT_TOO_LARGE |
Single document exceeded 50 MB. |
DOCUMENT_UNSUPPORTED |
File type not supported. |
KNOWLEDGE_COLLECTION_NOT_FOUND |
Linked-mode collection id missing or no access. |
ESCALATION_TRIGGER_INVALID |
Trigger config didn't validate (e.g. bad regex). |
ESCALATION_ACTION_FAILED |
Action attempted but downstream rejected (e.g. webhook 5xx). |
TONE_INVALID |
Tone field combination not allowed. |