Skip to content
Sursa Developers

POST/v1/chat

Stream an assistant answer (SSE)

chat

With several API copies behind a load balancer (the api.<domain> address, 1.62.0), an answer and the buffer of its events live in the memory of the copy that generates it. Resuming the stream with Last-Event-ID works only on that copy.

A repeated request with the same request_id and conversation that reaches another copy after the answer has finished receives the saved answer (token and done, events numbered from 1) without asking the question again. A repeated request that reaches another copy while the answer is still being generated stops that generation and builds the answer anew; no second question is created either. To resume the stream without a new generation, keep the connection to the same copy or repeat the request after the done event.

Authentication

Send an API key in the Authorization header: Authorization: Bearer <key>.

Header parameters

  • X-View-Asstring

    For API keys with the admin role only. Makes the request as the data profile <profile>[:viewer|verifier|editor], for example employee:viewer. The installation key cannot use this header (403).

Cookie parameters

  • kb_view_asstring

    Cookie of the “View as” mode for a session. POST /auth/view-as sets it and DELETE /auth/view-as clears it.

Request body

application/json

Object: ChatRequest

  • messagesarray of ChatMessagerequired

    items ≥ 1

  • collectionstring

    Default: "default"

  • tagsarray of string | null
  • exportstring | null
  • card_idsarray of string | null

    items ≤ 50

  • streamboolean

    Default: false

  • conversation_idstring | null

    length ≤ 64

  • originstring | null
  • toolsboolean | null
  • bypass_cacheboolean

    Do not take the answer from the answer cache (the “Get a fresh answer” button under a cached answer). The fresh answer replaces the cached entry.

    Default: false

  • languagestring | null

    Answer language: an ISO 639-1 code (de, en, ru, …) to answer in that language. With auto or without the field, the language is detected from the question. The interface passes the language of a suggestion in another language explicitly (Starter.language).

  • scopeChatScope | null

    Scope of the question: several collections, a source, tags and a period. The collections of the scope replace collection. A source narrows the answer to its collection (and its own cards). Tags are added to tags. The period limits financial answers to that period. You can select only what the user can see (collections: collections.no_access/collections.not_found; source: sources.not_found). With conversation_id, the scope is saved in the conversation. Without the field, the conversation's scope applies; null or an empty scope clears it.

  • request_idstring

    Idempotency key of the question. Send the same key in every retry of the stream for one question (a retry after a disconnect; here Last-Event-ID does not continue the stream and is only logged). A retry with the key of an answer that is already saved does not create a second question: the saved result is sent again as one done event (and a token with the text), even if the question or credit limit is exhausted. If the previous answer is still being generated for a disconnected client, that generation stops and the answer is generated anew.

    length ≤ 64

  • version_ofinteger (int64)

    Creates a new version of this question's turn in the conversation (question_id from the feed): an edited question (new text in messages), a regenerated answer (the same text, usually with bypass_cache), or the same question with another quality (for example, precise after a fast answer). The previous question and answer pair is kept. The turns after it stay in its branch and are hidden from the feed while the new version is selected (FeedItem.versions, POST /v1/conversations/{conv_id}/versions). The history used for the answer is the selected branch up to this turn. The quality of a version does not change the conversation's settings. Requires conversation_id; a question from another conversation returns 404 questions.not_found.

  • qualitystring

    Balance between speed and accuracy of the search behind the result: fast is quicker, precise is more accurate. Default: precise.

    Allowed values: fastprecise

Responses

200With `stream=true`: `text/event-stream`. Each event consists of the lines `id: <number>` (the sequence number of the event in the stream, starting at 1) and `data: <JSON>`, followed by an empty line. The `event:` and `retry:` fields are not used; the event type is in the `type` field (`ChatEvent`).

With stream=true: text/event-stream. Each event consists of the lines id: <number> (the sequence number of the event in the stream, starting at 1) and data: <JSON>, followed by an empty line. The event: and retry: fields are not used; the event type is in the type field (ChatEvent).

A question with request_id is answered independently of the connection. A disconnect does not stop the answer: it is completed and saved in the conversation (for up to 10 minutes). Repeating the same request (the same request_id and conversation) attaches to the answer in progress, and with the Last-Event-ID header it receives the events after that number, so the stream continues with the same event numbers. If the stream cannot continue from that number, the repeated request gets the stream from the start: the first event then has a number no greater than Last-Event-ID, and the client starts the answer over. If the answer has already finished and its event buffer has been released (after 3 minutes), the saved result is sent again (token and done, numbered from 1) without asking the question again; otherwise the answer is generated anew. To stop such an answer, call POST /v1/chat/cancel. Without request_id, a client disconnect cancels the answer.

After the first event, while the answer is in progress, the server sends a : ping comment every 15 seconds; skip it. Event order: stage events (progress), meta, sources, data, then the answer text in token events, then done. Before the answer text, sources and data can repeat and tool events can appear; the text can arrive as one token or in parts. A cached answer: meta (with cached), sources, data, token, done. An error after the stream has started arrives as an error event, and the stream closes without done; the HTTP status of the stream is always 200. After done, a followups event with suggested next questions can arrive. Ignore event types you do not handle.

With stream=false: application/json with an AnswerResponse body (plus conversation_id).

Response headers

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: AnswerResponse

  • answerstringrequired
  • question_idintegerrequired
  • querystring
  • collectionstringrequired
  • sourcesarray of Sourcerequired
  • table_queriesarray of TableQueryrequired
  • datasetsarray of Datasetrequired
  • chartsarray of ChartSpecrequired
  • warningsarray of AnswerWarningrequired
  • timingsTimingsrequired
  • provenancearray of NumberProvenance
  • emptystring

    Allowed values: no_hitsrestrictedguardrailno_data_for_period

  • verificationAnswerVerification
  • alt_periodsarray of AnswerAltPeriod

    items ≤ 6

  • drilldownarray of AnswerDrilldown

    items ≤ 20

  • restrictedRestrictedInfo
  • verified_onlyboolean
  • cachedboolean
  • out_of_scopeAnswerOutOfScope
  • attachmentsarray of Attachment
  • export_errorstring
  • toolsstring | null

    Why tools were used for this answer: request (asked for explicitly); compare, compute, action (based on the question); needs_calc (a calculation over tables is needed); summary (an overview of a collection or documents); mcp (the organization has connected external MCP servers).

    Allowed values: requestcomparecomputeactionneeds_calcsummarymcpnull

  • tool_callsarray of ToolCallInfo
  • calculationsarray of Calculation
  • pending_actionsarray of PendingAction
  • entitiesarray of AnswerEntityrequired
  • followupsarray of Followuprequired
  • conversation_idstring

    Only for POST /v1/chat with a conversation.

  • answer_idstring

    ID of the answer object.

400The request is invalid: a parameter value or the state of the object does not allow the action (`detail` is a message).

Response headers

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: Error

401No credentials were sent (neither a session cookie nor an API key), or the key was not found.

Response headers

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: Error

403The action is not allowed: the role is insufficient, there is no access to the collection or card, the request runs in “View as” mode, or the organization is suspended or deleted (`detail` is an object with `code: org_suspended | org_deleted`).

Response headers

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: Error

404The object does not exist or is not available to you. The API does not confirm that a restricted object exists.

Response headers

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: Error

422Validation error: the body or parameters do not match the schema (`detail` is a list of validation errors), or a parameter value is out of range (`detail` is a message).

Response headers

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: Error

429Too many requests (`api.rate_limited`), the organization's quota for the minute, day or month is used up (`api.quota_exceeded`; `error.details` holds `quota`, `limit` and `reset_at`), the organization's limit is reached, or the answer service is busy (`answers.engine_busy`). Wait for the time in the `Retry-After` header.

Response headers

  • Retry-After

    Number of seconds to wait before you retry the request.

  • RateLimit-Policy

    Limits in effect, in the format of the IETF draft draft-ietf-httpapi-ratelimit-headers: comma-separated items "<name>";q=<quota>;w=<window in seconds>. key is the request rate of the API key (the quota is the burst, the window is the time to refill it fully; for a session it is user, without credentials ip); minute, day and month are the organization's quotas for the calendar minute, day and month in UTC.

  • RateLimit

    What is left of each limit in RateLimit-Policy: "<name>";r=<remaining>;t=<seconds until reset>.

  • X-RateLimit-Limit

    Limit of the strictest entry in RateLimit-Policy (the one with the fewest requests left).

  • X-RateLimit-Remaining

    Requests left under the strictest limit.

  • X-RateLimit-Reset

    Seconds until the strictest limit resets.

application/json

Object: Error

Error codes

Codes this endpoint can return in error.code, besides the general codes of every request.

Safe retries

Send an Idempotency-Key header (for example a UUID) with each POST and PATCH. A retry with the same key within 24 hours returns the saved response instead of running the request again.

Rate limits

Responses carry the RateLimit and RateLimit-Policy headers and the earlier X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. A 429 response has Retry-After in seconds: wait and retry.

← answers · API reference