Skip to main content
POST
/
chat
/
query
/
cURL
curl --request POST \
  --url https://api-prod.voltai.ai/chat/query/ \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "query": "<string>",
  "user_id": "<string>",
  "chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "reasoning_level": "medium",
  "mode": "AUTO",
  "topic_names": [
    "<string>"
  ],
  "topic_name": "<string>"
}
'
{
  "final_answer": "<string>",
  "thinking": "<string>",
  "chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "chat_url": "<string>",
  "conversation_id": 123,
  "sources": [
    {
      "source_name": "<string>",
      "page": 123,
      "url": "<string>",
      "id": "<string>",
      "type": "<string>",
      "display_name": "<string>"
    }
  ],
  "mode": "<string>",
  "tools": [
    {
      "id": "<string>",
      "name": "<string>",
      "display_name": "<string>",
      "title": "<string>",
      "input": {},
      "output": "<string>",
      "subagent_instance_id": "<string>"
    }
  ],
  "content": [
    {
      "type": "text",
      "text": "<string>",
      "subagent_instance_id": "<string>"
    }
  ]
}
Use POST /chat/query/ to ask a question and optionally continue the same conversation by sending back the returned chat_id. The agent automatically chooses which topics, tools, and subagents to use; you can scope retrieval to specific knowledge topics with topic_names and bias the agent’s reasoning depth with reasoning_level. Send your API key in the X-API-KEY header. The body must include query and user_id.

Request Notes

  • user_id (required) — your application’s identifier for the end-user making the request. Each (API key, user_id) pair is limited to one concurrent request. If the same user already has a request in flight, the endpoint returns 429.
  • chat_id (optional) — must be a valid UUID. Behavior:
    • Omitted → the server mints a fresh UUID and creates a new chat.
    • UUID matches an existing chat in your organization → the new turn is appended to that thread.
    • UUID is well-formed but not yet used → the server creates a new chat under that UUID. This lets clients pin their own thread IDs for idempotency or app-side correlation.
    • UUID already belongs to a chat you cannot resume (different org or soft-deleted) → 409.
    • UUID malformed → 400.
  • reasoning_level controls how thorough the agent should be. Defaults to medium.
    • low — favor quick answers and minimal tool use.
    • medium — default.
    • high — favor thorough multi-step reasoning with more tool calls.
    Unknown values fall back to medium.
  • mode is a legacy field kept for backwards compatibility. The current agent pipeline does not branch on it; whatever you send is echoed back unchanged on the response. Use reasoning_level instead.
  • topic_names (optional) — list of knowledge topic names to scope retrieval to (e.g. ["Family A", "Family B"]). Each name must match a topic in your organization (case-insensitive). If omitted or [], topic scope is chosen automatically. If any name does not match a topic, the endpoint returns 400.
  • topic_name (deprecated) — singular alias for topic_names. When topic_names is omitted, topic_name is wrapped into a one-element list. Prefer topic_names for new integrations.

Response Notes

  • The endpoint returns a single JSON object, not an array.
  • final_answer is the cleaned answer text. Internal markup (<answer>, <ref>, <abbr>, citation tokens) is stripped.
  • chat_id is the chat thread UUID. Pass it back on subsequent requests to continue the conversation.
  • chat_url is the web UI link for this thread: https://voltai.ai/{org_name}/chat/{chat_id}, where {org_name} is the resolved organization’s name.
  • conversation_id is the integer identifier of this specific question/answer turn. A new conversation_id is returned for every /chat/query/ request, including follow-ups in the same chat_id. Use it to fetch the same turn later via GET /chat/conversation/{conversation_id}/.
  • sources lists evidence cited by the agent. Each entry includes:
    • id — stable identifier; use it to join citation tokens that appear in final_answer (e.g. [0351-E1]) back to a specific source.
    • source_name — filename for library / PDF chunks; page or item title for web, fetched URLs, and connector sources (Slack, Jira, Confluence, Salesforce, SharePoint, Assembla); display label for part sources.
    • page — 1-indexed page number for paginated library sources; null otherwise.
    • type — source type tag (text, web, part, etc.).
    • url — link to view the source. May be null for sources without a canonical link.
    • display_name — human-readable label for the tool that surfaced the source (e.g. "Library Search", "Web Search", "Part Detail").
  • tools is the ordered list of tool calls the agent made while answering — same data SSE clients receive as tool_call / tool_output frames. Each entry has id, name, display_name, title, input, output, status, and an optional subagent_instance_id.
  • content is the raw transcript of the turn: an ordered list of text and tool items as the agent produced them. text items concatenate to final_answer; tool items mirror tools.
  • thinking is retained for backwards compatibility with the legacy multi-agent orchestrator. Under the current agent pipeline it is always "" — use tools and content to inspect the reasoning trail.
  • mode echoes whatever value you sent (or "AUTO" if omitted). It does not reflect any internal routing decision.

Concurrency & Sessions

Each (API key, user_id) pair is limited to one concurrent request. If a second request arrives for the same pair while one is still in progress, the API returns 429 with error code user_session_limit_exceeded. There is also an organization-wide session limit. If all org-level seats are occupied, the API returns 429 with error code session_limit_exceeded. Use GET /chat/sessions/ to check current session usage and see which user IDs are active.

Streaming with Server-Sent Events

Set Accept: text/event-stream to receive incremental output instead of the single JSON response. The stream begins with one start event, then interleaved text, tool_call, tool_output, todos, and interrupt events as the agent runs, and ends with either one done event (success) or one error event (failure). Comment frames (: keepalive) may appear between frames while the server waits on the model; ignore them.
EventDescription
startSent once at the top of the stream so clients can render thread context immediately. Carries chat_id, chat_url, conversation_id.
textIncremental answer text. msg.delta is the fragment to append; msg.subagent_instance_id is non-null when the delta comes from a subagent (intermediate reasoning, not user-facing).
tool_callThe agent started a tool call. msg contains id, name, display_name, title, input, and subagent_instance_id.
tool_outputThe corresponding tool call finished. msg contains id, output, status (running | success | error).
todosSnapshot of the agent’s TODO list for multi-step plans. Replaces (not appends) any prior list for the same subagent_instance_id.
interruptHuman-in-the-loop interrupt. The agent is asking you to approve or reject an action.
doneTerminal success frame with the same payload as the non-streaming JSON response (including tools, content, sources).
errorTerminal failure frame. Sent if the stream fails after the 200 response status has been committed.
Concatenating the msg.delta text from every main-agent text event (those with subagent_instance_id == null) reproduces a close approximation of final_answer; rely on the done event’s final_answer for the canonical cleaned string.

Example Request

{
  "query": "What is EMEM?",
  "user_id": "usr_82af91",
  "reasoning_level": "medium"
}

Scoped to one or more topics (optional)

{
  "query": "What is the maximum operating temperature?",
  "user_id": "usr_82af91",
  "topic_names": ["Example Product Family"]
}

Follow-up Request (continuing a thread)

{
  "query": "What is the maximum operating temperature?",
  "user_id": "usr_82af91",
  "chat_id": "2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54"
}

Example Response

{
  "final_answer": "EMEM is embedded memory integrated into the device for storing code and data.",
  "thinking": "",
  "chat_id": "2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54",
  "chat_url": "https://voltai.ai/ExampleOrg/chat/2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54",
  "conversation_id": 184217,
  "sources": [
    {
      "id": "0351-E1",
      "source_name": "example-datasheet.pdf",
      "page": 12,
      "type": "text",
      "url": "https://voltai.ai/ExampleOrg/library?source_name=example-datasheet.pdf&source_type=text&source_page=12",
      "display_name": "Library Search"
    }
  ],
  "mode": "AUTO",
  "tools": [
    {
      "id": "call_8c2f",
      "name": "search_library",
      "display_name": "Library Search",
      "title": "Searching \"EMEM\" in Datasheets",
      "input": { "query": "EMEM", "topic_id": 17 },
      "output": "Found 3 matching chunks…",
      "status": "success",
      "subagent_instance_id": null
    }
  ],
  "content": [
    {
      "type": "tool",
      "id": "call_8c2f",
      "name": "search_library",
      "display_name": "Library Search",
      "title": "Searching \"EMEM\" in Datasheets",
      "input": { "query": "EMEM", "topic_id": 17 },
      "output": "Found 3 matching chunks…",
      "status": "success",
      "subagent_instance_id": null
    },
    {
      "type": "text",
      "text": "EMEM is embedded memory integrated into the device for storing code and data.",
      "subagent_instance_id": null
    }
  ]
}

Example SSE Stream

data: {"type":"start","chat_id":"2d8a…","chat_url":"https://voltai.ai/ExampleOrg/chat/2d8a…","conversation_id":184217}

data: {"type":"tool_call","msg":{"id":"call_8c2f","name":"search_library","display_name":"Library Search","title":"Searching \"EMEM\" in Datasheets","input":{"query":"EMEM"},"subagent_instance_id":null}}

data: {"type":"tool_output","msg":{"id":"call_8c2f","output":"Found 3 matching chunks…","status":"success"}}

data: {"type":"text","msg":{"delta":"EMEM is embedded memory","subagent_instance_id":null}}

data: {"type":"text","msg":{"delta":" integrated into the device.","subagent_instance_id":null}}

data: {"type":"done","final_answer":"EMEM is embedded memory integrated into the device.","thinking":"","chat_id":"2d8a…","chat_url":"https://voltai.ai/ExampleOrg/chat/2d8a…","conversation_id":184217,"sources":[...],"mode":"AUTO","tools":[...],"content":[...]}

409 — Chat ID conflict

{
  "detail": "chat_id is already in use."
}

429 — Per-User Limit

{
  "error": "user_session_limit_exceeded",
  "message": "user_id 'usr_82af91' already has an active request. Please wait for it to complete.",
  "user_id": "usr_82af91"
}

429 — Org-Level Limit

{
  "error": "session_limit_exceeded",
  "message": "You have exceeded the session quota limit for your organization. Please try again later.",
  "total_seats": 10,
  "active_seats": 10,
  "available_seats": 0
}

Authorizations

x-api-key
string
header
required

Headers

Accept
enum<string>

Set to text/event-stream to opt into Server-Sent Events streaming. Any other value (or omitting the header) returns the standard JSON response.

Available options:
application/json,
text/event-stream

Body

application/json

Query payload for the Voltai agent.

Provide query and user_id. Topic scope is chosen automatically unless you pass topic_names. The agent decides its own reasoning depth — use reasoning_level to bias it.

query
string
required

The user's question.

user_id
string
required

Your application's identifier for the end-user making the request. Used for per-user session tracking and concurrency enforcement. Each (API key, user_id) pair is limited to one concurrent request.

Maximum string length: 255
chat_id
string<uuid>

Existing chat thread to continue. Must be a valid UUID. If it matches a chat in your organization, the new turn is appended; if the UUID is well-formed but not yet used, the server creates a new chat under that UUID (useful for client-side idempotency / correlation). Omit to let the server mint a fresh UUID. A UUID that already belongs to a chat the API key cannot resume returns 409.

reasoning_level
enum<string>
default:medium

Bias for how much intermediate reasoning the agent should do. low favors quick answers, high favors thorough multi-step reasoning. Unknown values fall back to medium.

Available options:
low,
medium,
high
mode
enum<string>
default:AUTO

Legacy reasoning-mode selector kept for backwards compatibility with older clients. Under the current agent pipeline this is a no-op — the value is validated and echoed back on the response, but it does not change behavior. Use reasoning_level instead.

Available options:
AGENTIC,
FAST,
AUTO
topic_names
string[]

Optional. Names of knowledge topics to scope retrieval to. Each must match a topic in your organization (case-insensitive). If omitted or empty, topic scope is chosen automatically. If any name does not match a topic, the request returns 400.

topic_name
string
deprecated

Deprecated singular alias for topic_names. When topic_names is omitted, topic_name (if present) is wrapped into a one-element list. Prefer topic_names for new integrations.

Response

Agent response. Returned as a single JSON object by default, or as a Server-Sent Events stream when the request includes Accept: text/event-stream.

Agent response.

final_answer
string
required

Cleaned answer text returned by the agent. Internal markup (<answer>, <ref>, <abbr>, citation tokens) is stripped.

thinking
string
required

Aggregated reasoning string from the legacy multi-agent orchestrator: per-agent entries are concatenated in execution order, each prefixed by a header line and separated by a blank line. Empty under the current agent pipeline — use tools and content to inspect the reasoning trail instead.

chat_id
string<uuid>
required

Thread identifier: the Chat UUID for this conversation. Reuse this value in subsequent requests to continue the same thread.

chat_url
string<uri>
required

Web UI link to this thread: https://voltai.ai/{organization_name}/chat/{chat_id} using the resolved organization's name.

conversation_id
integer
required

Identifier of the specific question/answer turn within the thread. A new conversation_id is generated for every /chat/query/ request. Use it with GET /chat/conversation/{conversation_id}/ to fetch this exact turn later.

sources
object[]
required

Evidence cited by the agent. Each entry is annotated with the tool that surfaced it (display_name) and a stable id for joining back to citation tokens in final_answer.

mode
string | null
required

Echo of the request mode. Retained for backwards compatibility; current agent behavior does not depend on it.

tools
object[]
required

Every tool call the agent made while answering this turn, in execution order. Lets non-streaming clients see the same reasoning trail that SSE clients receive as live tool_call / tool_output frames.

content
object[]
required

Raw agent transcript for the turn: an ordered list of text and tool items as the agent produced them. text items concatenate to final_answer; tool items mirror the entries in tools.

Text fragment emitted by the agent (main agent or a subagent). Concatenate all main-agent text items in order to reconstruct the agent's prose.