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",
"topic_names": [
"<string>"
],
"topic_name": "<string>"
}
'import requests
url = "https://api-prod.voltai.ai/chat/query/"
payload = {
"query": "<string>",
"user_id": "<string>",
"chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reasoning_level": "medium",
"topic_names": ["<string>"],
"topic_name": "<string>"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '<string>',
user_id: '<string>',
chat_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
reasoning_level: 'medium',
topic_names: ['<string>'],
topic_name: '<string>'
})
};
fetch('https://api-prod.voltai.ai/chat/query/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-prod.voltai.ai/chat/query/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => '<string>',
'user_id' => '<string>',
'chat_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'reasoning_level' => 'medium',
'topic_names' => [
'<string>'
],
'topic_name' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-prod.voltai.ai/chat/query/"
payload := strings.NewReader("{\n \"query\": \"<string>\",\n \"user_id\": \"<string>\",\n \"chat_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reasoning_level\": \"medium\",\n \"topic_names\": [\n \"<string>\"\n ],\n \"topic_name\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-prod.voltai.ai/chat/query/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"<string>\",\n \"user_id\": \"<string>\",\n \"chat_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reasoning_level\": \"medium\",\n \"topic_names\": [\n \"<string>\"\n ],\n \"topic_name\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-prod.voltai.ai/chat/query/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"<string>\",\n \"user_id\": \"<string>\",\n \"chat_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reasoning_level\": \"medium\",\n \"topic_names\": [\n \"<string>\"\n ],\n \"topic_name\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"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>"
}
],
"tools": [
{
"id": "<string>",
"name": "<string>",
"status": "running",
"display_name": "<string>",
"title": "<string>",
"input": {},
"output": "<string>",
"subagent_instance_id": "<string>"
}
],
"content": [
{
"type": "text",
"text": "<string>",
"subagent_instance_id": "<string>"
}
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"error": "user_session_limit_exceeded",
"message": "<string>",
"user_id": "<string>",
"total_seats": 123,
"active_seats": 123,
"available_seats": 123
}Chat Query
Ask a question to the Voltai agent and continue an existing thread with chat_id.
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",
"topic_names": [
"<string>"
],
"topic_name": "<string>"
}
'import requests
url = "https://api-prod.voltai.ai/chat/query/"
payload = {
"query": "<string>",
"user_id": "<string>",
"chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reasoning_level": "medium",
"topic_names": ["<string>"],
"topic_name": "<string>"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '<string>',
user_id: '<string>',
chat_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
reasoning_level: 'medium',
topic_names: ['<string>'],
topic_name: '<string>'
})
};
fetch('https://api-prod.voltai.ai/chat/query/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-prod.voltai.ai/chat/query/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => '<string>',
'user_id' => '<string>',
'chat_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'reasoning_level' => 'medium',
'topic_names' => [
'<string>'
],
'topic_name' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-prod.voltai.ai/chat/query/"
payload := strings.NewReader("{\n \"query\": \"<string>\",\n \"user_id\": \"<string>\",\n \"chat_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reasoning_level\": \"medium\",\n \"topic_names\": [\n \"<string>\"\n ],\n \"topic_name\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-prod.voltai.ai/chat/query/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"<string>\",\n \"user_id\": \"<string>\",\n \"chat_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reasoning_level\": \"medium\",\n \"topic_names\": [\n \"<string>\"\n ],\n \"topic_name\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-prod.voltai.ai/chat/query/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"<string>\",\n \"user_id\": \"<string>\",\n \"chat_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reasoning_level\": \"medium\",\n \"topic_names\": [\n \"<string>\"\n ],\n \"topic_name\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"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>"
}
],
"tools": [
{
"id": "<string>",
"name": "<string>",
"status": "running",
"display_name": "<string>",
"title": "<string>",
"input": {},
"output": "<string>",
"subagent_instance_id": "<string>"
}
],
"content": [
{
"type": "text",
"text": "<string>",
"subagent_instance_id": "<string>"
}
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"error": "user_session_limit_exceeded",
"message": "<string>",
"user_id": "<string>",
"total_seats": 123,
"active_seats": 123,
"available_seats": 123
}POST /chat/query/ to ask a question. Send X-API-KEY in the header; the body must include query and user_id. To continue a conversation, pass back the chat_id from a previous response.
Request
user_id(required) — your identifier for the end-user. Each(API key, user_id)pair allows one concurrent request; a second in-flight request returns429.chat_id(optional) — UUID of the thread to continue. Omit to start a new thread; the server returns a freshchat_id. A malformed UUID returns400; a UUID you can’t access returns409.reasoning_level(optional) —low,medium(default), orhigh. Higher levels favor more thorough answers.topic_names(optional) — list of knowledge topic names to scope retrieval to (e.g.["Family A"]). Names are case-insensitive; an unknown name returns400. Omit to let the agent choose.
Response
final_answer— the answer text.chat_id— thread UUID; pass it back to continue the conversation.chat_url— web link to view this thread.conversation_id— integer ID for this specific turn. Use it to fetch the turn later viaGET /chat/conversation/{conversation_id}/.sources— evidence cited in the answer. Each entry hasid,source_name,page,type,url, anddisplay_name. Join a source’sidto citation tokens infinal_answer(e.g.[0351-E1]).tools— ordered list of tool calls the agent made, each withid,name,display_name,title,input,output, andstatus.
Streaming
SetAccept: text/event-stream to receive incremental output instead of a single JSON response. The stream opens with a start event, emits text, tool_call, tool_output, and todos (progress) events as the agent runs, and ends with a done event (whose payload matches the JSON response) or an error event.
Example Request
{
"query": "What is EMEM?",
"user_id": "usr_82af91",
"reasoning_level": "medium"
}
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.",
"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"
}
],
"tools": [
{
"id": "call_8c2f",
"name": "search_library",
"display_name": "Library Search",
"title": "Searching \"EMEM\" in Datasheets",
"input": { "query": "EMEM" },
"output": "Found 3 matching chunks…",
"status": "success"
}
],
"content": [
{
"type": "tool",
"id": "call_8c2f",
"name": "search_library",
"display_name": "Library Search",
"title": "Searching \"EMEM\" in Datasheets",
"input": { "query": "EMEM" },
"output": "Found 3 matching chunks…",
"status": "success"
},
{
"type": "text",
"text": "EMEM is embedded memory integrated into the device for storing code and data."
}
]
}
Errors
- 409 —
chat_idbelongs to a thread you can’t resume. - 429 — per-user (
user_session_limit_exceeded) or org-wide (session_limit_exceeded) session limit reached. UseGET /chat/sessions/to check usage.
Authorizations
Headers
Set to text/event-stream to opt into Server-Sent Events streaming. Any other value (or omitting the header) returns the standard JSON response.
application/json, text/event-stream Body
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.
The user's question.
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.
255Existing 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.
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.
low, medium, high 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.
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.
Cleaned answer text returned by the agent. Internal markup (<answer>, <ref>, <abbr>, citation tokens) is stripped.
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.
Thread identifier: the Chat UUID for this conversation. Reuse this value in subsequent requests to continue the same thread.
Web UI link to this thread: https://voltai.ai/{organization_name}/chat/{chat_id} using the resolved organization's name.
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.
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.
Show child attributes
Show child attributes
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.
Show child attributes
Show child attributes
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.
- Option 1
- Option 2
Show child attributes
Show child attributes