View as Markdown →
Errors & limits
#HTTP status codes
| Status | Typical cause |
|---|---|
| 401 | Missing, invalid, or expired API key |
| 403 | Wrong organisation, missing permission, source not allowed, widget rejected the request, or conversation does not belong to this visitor |
| 404 | Unknown organisation, source, page, widget, or conversation |
| 402 | No answer credits left (chat and summarize) |
| 422 | Invalid input, identity check failed, or keep limit reached |
| 429 | Too many requests |
#Invalid input
When a required field is missing or invalid, the body looks like this:
{
"message": "The content field is required.",
"errors": {
"content": ["The content field is required."]
}
}
message is a human-readable summary. errors maps each field name to one or more messages.
#Rate limits
Limits are counted per minute.
#Ingestion API
Counted per API key (or IP if there is no key).
| Area | Default |
|---|---|
| Page push and related routes | 120 requests per minute |
#Widget API
Each group has a limit for the whole widget and a lower limit for a single visitor (widget + IP), so one visitor cannot use up the entire budget.
| Group | Endpoints | Defaults (widget / visitor) |
|---|---|---|
| Search | search | 60 / 20 |
| AI | chat, summarize | 20 / 6 |
| Events | events | 120 / 30 |
| Config | config, conversations | 300 / 60 |
Exceeding a limit returns 429.
#Answers and billing
- Search and page ingestion do not use answer credits.
- Chat and summarize use your plan's monthly answers.
- When answers are used up, those endpoints return 402.
- Chat attaches free search hits in
data(same hit shape as the search endpoint) so the official embed can show results without a second request. Example:
{
"error": "answers_exhausted",
"message": "AI answers are paused for this site — search still works.",
"fallback": "search",
"data": [
{ "id": "…", "external_id": null, "name": "…", "url": "…", "snippet": "…", "score": 0.5, "meta": null }
],
"session_id": "…"
}
- Summarize returns the same error fields without a result list.
#Tips for reliable page sync
- Always send a stable
external_idso retries update the same page instead of creating duplicates. - Re-pushing identical content for an already indexed page is skipped.
- Batch requests accept at most 50 pages at a time.