Skip to main content
POST
Handle Send Chat Message
Required permission: Chat — Write (write:chat), which basic includes, so any signed-in user has it. A limited Personal Access Token needs the Chat — Write scope. A service account in no group also holds it. Anonymous users can call this when anonymous access is enabled.
Multi-model requests must stream. Passing llm_overrides with more than one entry runs the models in parallel and requires stream=true; combining it with stream=false returns 400 {"error_code": "INVALID_INPUT"}. A single-entry llm_overrides list is ignored — use llm_override for an ordinary single-model override.

Authorizations

Authorization
string
header
required

Authorization header with Bearer token

Body

application/json
message
string
required
llm_override
LLMOverride · object | null

Per-request LLM settings that override persona defaults.

All fields are optional — only the fields that differ from the persona's configured LLM need to be supplied. Used both over the wire (API requests) and for multi-model comparison, where one override is supplied per model.

Attributes: model_configuration_id: Exact model configuration to use. Preferred over the name-based fields — provider display names are not unique, so only the id routes unambiguously. model_provider: LLM provider display name. When None, the persona's default provider is used. model_version: Specific model version string (e.g. "gpt-4o"). When None, the persona's default model is used. temperature: Sampling temperature in [0, 2]. When None, the persona's default temperature is used. display_name: Human-readable label shown in the UI for this model, e.g. "GPT-4 Turbo". Optional; falls back to model_version when not set.

llm_overrides
LLMOverride · object[] | null

Two or three LLM overrides to run in parallel (multi-model mode), one entry per model. Requires stream=true: a request carrying more than one entry with stream=false is rejected with a 400 INVALID_INPUT error. A list with a single entry is ignored — use llm_override to change the model for an ordinary single-model request.

allowed_tool_ids
integer[] | null
forced_tool_id
integer | null
file_descriptors
FileDescriptor · object[]
internal_search_filters
BaseFilters · object | null
deep_research
boolean
default:false
mcp_headers
Mcp Headers · object | null

Headers forwarded to MCP tool calls made while answering this message, e.g. {"Authorization": "Bearer <user_jwt>", "X-User-ID": "user123"}. Use this to pass end-user credentials through to MCP servers that require them.

origin
enum<string>
default:unset

Origin of a chat message for telemetry tracking.

Available options:
webapp,
chrome_extension,
api,
slackbot,
widget,
discordbot,
mobile,
unknown,
unset
parent_message_id
integer | null
default:-1
chat_session_id
string<uuid> | null
chat_session_info
ChatSessionCreationRequest · object | null
stream
boolean
default:true
include_citations
boolean
default:true
additional_context
string | null

A string of extra context injected into the LLM call for this request. The context is passed to the model but is not stored in the database and will not appear in the chat history. Use this to supply ephemeral, request-scoped information (e.g. the user's current page URL, session metadata, or any runtime context) without polluting the persistent conversation history. Pass null or omit the field to use no additional context.

Response

If stream=true, returns text/event-stream. If stream=false, returns application/json (ChatFullResponse).

Complete non-streaming response with all available data.

answer
string
required
answer_citationless
string
required
top_documents
SearchDoc · object[]
required
citation_info
CitationInfo · object[]
required
message_id
integer
required
pre_answer_reasoning
string | null
tool_calls
ToolCallResponse · object[]
chat_session_id
string<uuid> | null
incognito
boolean
default:false
error_msg
string | null