Chatbots API
All endpoints require session authentication and operate only on chatbots your account owns.
Create a chatbot
POST /chatbots
{
"name": "Northgate Assistant"
}
name is the only field accepted at creation. Everything else is set afterwards
with a PATCH.
Returns 201 with data.chatbot.
403 Chatbot limit reached for your plan if you already have as many chatbots
as your plan allows.
List chatbots
GET /chatbots
Returns data.chatbots — every chatbot your account owns.
Get a chatbot
GET /chatbots/:id
Returns data.chatbot with its full configuration.
Update a chatbot
PATCH /chatbots/:id
Send only the fields you want to change.
{
"welcomeMessage": "Hi! Ask me about delivery, returns or opening hours.",
"primaryColor": "#5b3df5",
"tone": "Friendly"
}
Updatable fields
| Field | Type | Notes |
|---|---|---|
name | string | Shown in the widget header |
description | string | Internal reference only |
avatarUrl | string | Set this from the image upload endpoint's response |
primaryColor | string | Hex, e.g. #5b3df5 |
theme | object | bg, panelBg, headerBg, bubbleBotBg, bubbleBotText, textMuted, border, inputBg |
welcomeMessage | string | Markdown supported |
quickPrompts | string[] | Suggested questions |
chatbotModel | string | gpt-4o-mini or gpt-4o |
persona | string | e.g. Helpful Assistant |
tone | string | e.g. Professional |
systemPrompt | string | See System prompt |
allowLeadCapture | boolean | |
leadCaptureFields | object | { name, email, phone }, booleans |
humanHandoffEnabled | boolean | |
humanHandoffEmail | string | Notification address |
autoRefreshSchedule | string | none, daily, weekly, monthly |
embedDomains | string[] |
Fields outside this list — ownerId, status, page and chunk counters, the
vector collection name — are silently dropped rather than applied. They are
maintained by the service and cannot be set from a request.
Returns the updated data.chatbot.
Delete a chatbot
DELETE /chatbots/:id
Deletes the chatbot and everything attached to it: data sources, indexed content, conversations and widget keys.
{
"success": true,
"message": "Chatbot and all related data deleted successfully"
}
There is no soft delete and no recovery. Any widget still embedded with this chatbot's key stops working immediately.
Training status
GET /chatbots/:id/status
Returns the chatbot's current status (idle, training, ready, error) along
with its page and chunk counts.
Poll this after triggering a crawl to know when indexing has finished. Poll sensibly — every few seconds, not continuously.
Recrawl everything
POST /chatbots/:id/recrawl
Re-ingests every data source attached to the chatbot. Returns immediately; the work happens in the background.
Rate-limited as an ingestion operation. See Rate limits.
Send a test message
POST /chatbots/:id/chat
The dashboard's own test chat. Unlike the widget endpoint, this is authenticated by session and does not need a widget key.
{
"message": "What are your opening hours?"
}
Returns:
{
"success": true,
"data": {
"response": "We're open Monday to Friday, 9am to 5pm.",
"sources": []
}
}
This response is complete rather than streamed — useful for scripted testing of answer quality after a content change.
Conversation history
GET /chatbots/:id/history
Returns data.messages — the conversation history for this chatbot.
Leads
GET /chatbots/:id/leads
Returns conversations where a visitor submitted contact details through lead capture, with the conversation attached.
That pairing is the point: you get the contact details and the exchange that produced them, which is far more useful to a salesperson than an email address on its own.
Delete a lead
DELETE /chatbots/:id/leads/:conversationId
Use this to honour a deletion request.
Satisfaction
GET /chatbots/:id/satisfaction
Aggregates the thumbs up and thumbs down ratings visitors gave individual answers.
{
"success": true,
"data": {
"positive": 42,
"negative": 5,
"total": 47,
"rate": 89
}
}
rate is the percentage of rated answers that were positive.
rate is null when nothing has been ratedNot 0. "Nobody has rated anything" and "everybody hated it" must not look
identical on a dashboard. Handle null explicitly.