This endpoint speaks the OpenAI chat completions format. If your chatbot already uses an OpenAI client library, point the client’s base URL at Snoowl Answers, give it a secret key, and the assistant answers from your documents.
Accepts a secret key only. A website or preview key gets a 403.
Example
Section titled “Example”Request
Section titled “Request”| Field | Type | Description |
|---|---|---|
messages | array | Required. The conversation, oldest first. The last user message is the question. Earlier user and assistant messages are the conversation so far, of which the last six are used. |
stream | boolean | Optional. true sends the answer as server-sent events. See Streaming. |
user | string | Optional. Your ID for this conversation, shown as the session in Conversations. Up to 80 characters are kept. |
model | string | Accepted and ignored. The key decides which assistant answers. |
A message’s content can be a string or a list of parts. From a list, only the text parts are read.
What’s different from OpenAI
Section titled “What’s different from OpenAI”The format is OpenAI’s, but the assistant behind it isn’t a general chat model:
- System messages are ignored, and so are
tooland other roles. The assistant’s name, tone and guidance come from Assistant settings, so a caller can’t change the rules that keep answers to your documents. - Other parameters are ignored, including
temperature,max_tokens,n,toolsandresponse_format. usageis always zero. Each answer’s real token count and cost are in Conversations.- Streaming isn’t faster. The whole answer is written and checked before the first chunk is sent. See Streaming.
- Every answer is checked against your documents. A question the documents don’t cover gets your decline message as the reply, with
snoowl.statusset todeclined.
Response
Section titled “Response”The standard fields are filled as OpenAI fills them. The snoowl field carries what OpenAI’s format has no place for:
| Field | Description |
|---|---|
snoowl.status | answered, or declined when your documents don’t cover the question |
snoowl.citations | The documents the answer used, in the same form as POST /answer |
snoowl.answer_id | The answer’s ID, for POST /feedback. The id field is the same ID with chatcmpl- in front. |
OpenAI client libraries keep fields they don’t know. In the Python SDK, read them with reply.model_extra["snoowl"]; in JavaScript, with reply.snoowl.
Streaming
Section titled “Streaming”With "stream": true, the response is text/event-stream. Each event is a data: line holding a chat.completion.chunk:
- The first chunk has
delta: {"role": "assistant", "content": ""}. - The answer follows in pieces of about 40 characters, each as
delta: {"content": "…"}. - The last chunk has an empty
delta,finish_reason: "stop"and thesnoowlfield. - The stream ends with
data: [DONE].
The answer is complete before the first chunk is sent, because it’s checked against your documents as a whole. Streaming exists so that clients built for streaming work unchanged. It doesn’t make the first words arrive sooner. If something goes wrong, the error comes back as an ordinary JSON response with its status code, never partway through a stream.
Errors
Section titled “Errors”Errors use the error format, which OpenAI SDKs raise as their usual exceptions. A request with no user message gets a 400 “Send at least one user message”. The key is checked first, so a bad key gets a 401 even when the body is wrong too.