Appearance
Conventions & errors
What every endpoint has in common: how to send requests, what comes back, how errors look, and the limits that apply.
Requests
Paths end with a slash (/users/me/, /microservices/workflow/) except where the reference shows otherwise (the extractor and cost-tracker proxies: /microservices/data-extractor/tables, …/costs). Send exactly the path shown; a missing slash on a POST is not redirected.
JSON by default. Send Content-Type: application/json and a JSON body. Most endpoints also accept multipart/form-data or application/x-www-form-urlencoded with the same field names — the web app often sends form data — and file uploads always use multipart/form-data with the file under the field named in the reference (usually path or file).
Query parameters carry filters and options on GET (and on the few DELETEs that take them). Booleans accept true/false, 1/0, yes/no.
Identifiers. Users, tiles, boards, sessions and data sources use integer ids; workflows, documents, tags and queue requests use UUIDs; artifacts, tables and chart documents use opaque string ids. All are stable.
Timestamps are ISO 8601 in UTC with a Z suffix or an explicit offset, for example 2026-09-22T06:41:12.318Z. Send the same format.
Language. Some resources carry parallel Arabic fields (title_ar, description_ar, dashboard_name_ar) and some endpoints take language=en|ar. The user's language preference (see POST /users/profile/) sets the default for generated text.
Responses
Successful responses are JSON with the shape documented per endpoint. Three recurring shapes are worth knowing:
| Shape | Used by |
|---|---|
{"message": "…"} | Simple acknowledgements |
A DRF page: {"count", "next", "previous", "results": […]} | Paginated lists (workflows) |
A bare array […] | Most other lists |
Status codes follow HTTP convention: 200 on success, 201 when something was created, 202 when work was accepted and continues in the background, 204 with no body after a delete. A few endpoints return 201 on update or 200 on create for historical reasons; the reference records the real code.
Some endpoints stream instead of returning JSON — see Streaming & WebSockets.
Pagination
Only the workflow list and search paginate: ?page= and ?page_size= (default 10, maximum 100). Everything else returns the full list; use the endpoint's filters (type, kind, origin, date ranges) to narrow it.
Errors
Errors are JSON. The body shape depends on where the error came from:
| Body | Source | Example |
|---|---|---|
{"detail": "…"} (sometimes with "code") | Authentication, permissions, throttling, not-found, and most newer endpoints | {"detail": "Invalid or expired token."} |
{"error": "…"} | Many module endpoints | {"error": "workflow_id is required"} |
{"<field>": ["…"], "non_field_errors": ["…"]} | Validation of a serializer-backed body | {"username": ["A user with that username already exists."]} |
Read detail, then error, then field keys, and you will get a message in every case.
| Status | Meaning |
|---|---|
400 | The request is malformed or fails validation — fix and resend. |
401 | No valid access token. Refresh or sign in, then retry once. |
402 | The account's subscription has expired (only on deployments that enforce subscriptions; code: subscription_expired). Renew from the Plans page. |
403 | Signed in, but not allowed: not your resource, read-only share, staff-only endpoint. Do not refresh the token. |
404 | Not found — including resources that exist but that you cannot see. |
409 | Conflict: a concurrent edit (content_revision), a duplicate, a limit, or an action that is not applicable in the current state. |
413 | An upload would exceed the plan's storage (only on deployments that enforce the storage quota; code: storage_limit_exceeded). Delete files or upgrade. |
429 | Rate limit hit; wait for Retry-After seconds. |
502 / 503 / 504 | A backing service (agent, extractor, dashboard service, data store) is unreachable, not configured, or timed out. Retry later. |
Rate limits
Limits are per user (or per client IP for anonymous calls) and reset every minute:
| Scope | Limit | Applies to |
|---|---|---|
| Signed-in requests | 300 / minute | Everything, unless a narrower scope applies |
| Anonymous requests | 60 / minute per IP | Public endpoints (sign-in helpers, verification) |
| Sign-in | 10 / minute per account | POST /api/v1/token/login/ |
| Document status polling | 120 / minute | /semantic-search/documents/status/ |
| Webhook trigger & status | not limited | /microservices/workflow/webhook/, …/webhook/status/ |
A 429 carries {"detail": "Request was throttled. Expected available in N seconds."} and a Retry-After header. Long-polling clients should use the batched status endpoint rather than polling per document.
Sharing and ownership
Most resources have an owner and can be shared. The pattern is consistent:
- Owner: full control, including sharing and deleting.
- Shared with (
shared: [user ids], collaborators, documentusers): read — and for workflow editors and table grants, write — but never delete or re-share. - Organisation membership scopes directories and the assistant's data access; it does not by itself grant access to a colleague's private resources.
Endpoints answer 403 when you have some access but not enough, and 404 when you have none.
Soft deletes
Documents and workflows go to a trash when deleted (30-day retention by default) and can be restored; their delete responses carry purge_at. Everything else is deleted immediately. Where a delete removes more than the named object, a delete-impact/ endpoint describes the blast radius first — the app shows it in the confirmation dialog.
Encryption of chat messages
The web app encrypts Chat AI messages in the browser before storing them (AES-256-GCM with a per-user key). Messages stored through the API without that key are kept in plaintext (is_encrypted: false); see Chat AI for what that means when reading a thread back.
CORS
The API allows browser calls from the configured web-app origins only, with credentials. Server-side clients are unaffected. Signed media URLs and permanent links are plain GETs that any origin may fetch.