curl --request POST \
--url https://api-prod.voltai.ai/chat/query-async/ \
--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>",
"callback_url": "<string>"
}
'import requests
url = "https://api-prod.voltai.ai/chat/query-async/"
payload = {
"query": "<string>",
"user_id": "<string>",
"chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reasoning_level": "medium",
"topic_names": ["<string>"],
"topic_name": "<string>",
"callback_url": "<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>',
callback_url: '<string>'
})
};
fetch('https://api-prod.voltai.ai/chat/query-async/', 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-async/",
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>',
'callback_url' => '<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-async/"
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 \"callback_url\": \"<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-async/")
.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 \"callback_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-prod.voltai.ai/chat/query-async/")
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 \"callback_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"conversation_id": 123,
"chat_url": "<string>",
"status": "processing"
}{
"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 (Async)
Submit a question and get the answer later via polling or a webhook callback.
curl --request POST \
--url https://api-prod.voltai.ai/chat/query-async/ \
--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>",
"callback_url": "<string>"
}
'import requests
url = "https://api-prod.voltai.ai/chat/query-async/"
payload = {
"query": "<string>",
"user_id": "<string>",
"chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reasoning_level": "medium",
"topic_names": ["<string>"],
"topic_name": "<string>",
"callback_url": "<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>',
callback_url: '<string>'
})
};
fetch('https://api-prod.voltai.ai/chat/query-async/', 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-async/",
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>',
'callback_url' => '<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-async/"
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 \"callback_url\": \"<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-async/")
.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 \"callback_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-prod.voltai.ai/chat/query-async/")
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 \"callback_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"chat_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"conversation_id": 123,
"chat_url": "<string>",
"status": "processing"
}{
"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-async/ when you don’t want to hold an HTTP connection open while the agent works. It accepts the same body as POST /chat/query/ plus an optional callback_url, and returns 202 Accepted immediately with a conversation_id — the agent keeps running in the background.
Because the response comes back before the answer is ready, you must pick one of two ways to collect the result:
- Poll
GET /chat/conversation/{conversation_id}/until it reportsCompleted. - Callback — pass a
callback_urland Voltai POSTs the finished result to it.
callback_url you don’t need to poll; if you don’t, polling is the only way to get the answer.
Request
SendX-API-KEY in the header. The body must include query and user_id.
query(required) — the user’s question.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.callback_url(optional) — anhttp(s)URL. When set, the final result is POSTed here as JSON once the run finishes. An invalid URL returns400.chat_id(optional) — UUID of a thread to continue. Omit to start a new thread.reasoning_level(optional) —low,medium(default), orhigh.topic_names(optional) — list of knowledge topic names to scope retrieval to.
Response (202 Accepted)
The202 body confirms the turn was accepted; it does not contain the answer.
{
"chat_id": "b0331c9f-b5e2-4062-92d3-d701bb0b856d",
"conversation_id": 732538,
"chat_url": "https://voltai.ai/ExampleOrg/chat/b0331c9f-b5e2-4062-92d3-d701bb0b856d",
"status": "processing"
}
conversation_id — you need it to poll for or correlate the result.
Example Request
curl -X POST "https://api-prod.voltai.ai/chat/query-async/" \
-H "Content-Type: application/json" \
-H "X-API-KEY: $API_KEY" \
-d '{"query": "What is EMEM?", "user_id": "usr_82af91"}'
Option A — Poll for the result
If you did not pass acallback_url, poll GET /chat/conversation/{conversation_id}/ using the conversation_id from the 202 response. Check the status field on each response:
Processing— the agent is still working; wait a moment and poll again.Completed— the answer is ready; the body carries the fullPOST /chat/query/payload (final_answer,sources,tools, etc.).Failed— the turn stopped without producing an answer.
curl -s "https://api-prod.voltai.ai/chat/conversation/732538/" \
-H "X-API-KEY: $API_KEY"
status is no longer Processing. This endpoint is read-only and does not consume session capacity.
Option B — Receive a callback
If you pass acallback_url, you don’t need to poll. When the run finishes, Voltai sends a POST to that URL with the same JSON body that POST /chat/query/ returns (final_answer, chat_id, chat_url, conversation_id, sources, tools, content).
curl -X POST "https://api-prod.voltai.ai/chat/query-async/" \
-H "Content-Type: application/json" \
-H "X-API-KEY: $API_KEY" \
-d '{
"query": "What is EMEM?",
"user_id": "usr_82af91",
"callback_url": "https://your-app.example.com/voltai/webhook"
}'
- Accept a
POSTwith a JSON body and return quickly (a2xx). - Use
conversation_idto match the callback back to the original request. - Handle the failure shape — if the run fails, the callback body is
{"chat_id", "conversation_id", "status": "error", "error"}instead of the full answer.
GET /chat/conversation/{conversation_id}/.
Errors
- 400 — missing
query/user_id, malformedchat_id, unknowntopic_names, or an invalidcallback_url. - 403 — invalid or missing API key, the key lacks the
chatscope, or the org message limit is reached. - 409 —
chat_idwas supplied but the UUID is already in use by a chat the API key cannot resume (a different organization, or a soft-deleted chat). Pick a different UUID, or omitchat_idto let the server mint one. - 429 — the same
user_idalready has an in-flight request, or the org-wide session cap is reached. Check usage withGET /chat/sessions/.
Authorizations
Body
Same payload as POST /chat/query/, plus an optional callback_url.
Request body for POST /chat/query-async/. Identical to ChatQuery plus an optional callback_url for webhook delivery of the result.
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.
Optional http(s) URL. When provided, the final result is POSTed to this URL as JSON once the agent finishes. Must be a valid http(s) URL or the request returns 400. Omit it if you plan to poll GET /chat/conversation/{conversation_id}/ instead.
Response
The request was accepted and the agent is running in the background. Use conversation_id to poll GET /chat/conversation/{conversation_id}/, or wait for the callback_url webhook if one was supplied.
Acknowledgement returned immediately (202) by POST /chat/query-async/. The answer is not included — fetch it later via GET /chat/conversation/{conversation_id}/ or receive it on your callback_url.
Thread identifier for this conversation. Reuse it (as chat_id) in later requests to continue the same thread.
Identifier of the turn just created. Poll GET /chat/conversation/{conversation_id}/ with this value to fetch the answer once it is ready.
Web UI link to this thread.
Always processing: the turn was accepted and the agent is running in the background.
processing