POST /v1/query, the chat query endpoint reference
Endpoint
POST https://api.askvault.co/v1/querySynchronous JSON response. For streaming, use POST /v1/query/stream instead.
Authentication: Authorization: Bearer ak_xxx. See authentication.
Minimal request
curl -X POST https://api.askvault.co/v1/query \-H "Authorization: Bearer ak_xxx" \-H "Content-Type: application/json" \-d '{"query": "What is your refund policy?"}'import requests, osr = requests.post( "https://api.askvault.co/v1/query", headers={"Authorization": f"Bearer {os.environ['ASKVAULT_API_KEY']}"}, json={"query": "What is your refund policy?"}, timeout=15,)print(r.json())const r = await fetch("https://api.askvault.co/v1/query", {method: "POST",headers: { "Authorization": `Bearer ${process.env.ASKVAULT_API_KEY}`, "Content-Type": "application/json",},body: JSON.stringify({ query: "What is your refund policy?" }),});console.log(await r.json());Request parameters
The workspace is bound to the API key at creation time, so there is no workspace_id in the body.
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | The user's question. 1 to 4,000 characters. |
top_k | integer | No | Number of context chunks to retrieve. 1 to 20. Default 8. Higher values give the model more context. |
session_id | string | No | Per-end-user session identifier (max 200 chars). Use this to separate conversation history for each of your end users when building a multi-tenant API consumer. |
conversation_id | string | No | Continue a specific multi-turn conversation by passing the conversation_id from a prior response. Rolling out: not yet on for every workspace, so send the same session_id on every call for now. |
Response schema
{ "answer": "Refunds are available within 30 days of purchase. Submit a request at acme.co/refunds with your order number.", "sources": [ { "document_name": "Refund policy", "chunk_text": "Refunds are available within 30 days of purchase...", "url": "https://acme.co/policies/refunds", "relevance_score": 0.94 } ], "tokens_used": 187, "query_id": "8f14e45f-ceea-4e7a-a2d2-2f6c1b8a9f10", "conversation_id": "1c9e6679-7425-40de-944b-e07fc1f90ae7"}| Field | Type | Description |
|---|---|---|
answer | string | The grounded answer text. |
sources | array | The document chunks retrieved to ground the answer. |
sources[].document_name | string | Name of the source document. |
sources[].chunk_text | string | An excerpt of the retrieved passage. |
sources[].url | string | URL of the source page, if available. null for uploaded files without a URL. |
sources[].relevance_score | number | A relevance score; higher is more relevant. |
tokens_used | integer | Total tokens consumed (input + output). |
query_id | string | Unique ID for this query. Store in your logs for debugging. |
conversation_id | string | The conversation ID. Pass this back in subsequent queries to continue the conversation. |
Conversation continuity
To keep a multi-turn conversation together today, send the same session_id on every call for that end user. Continuing by conversation_id is rolling out (see the note below); once it is on, you can send it back like this:
{ "query": "Can I get a refund on a sale item?", "conversation_id": "1c9e6679-7425-40de-944b-e07fc1f90ae7"}AskVault loads prior turns of the conversation as context for the new query. The retrieval and answer both factor in the conversation history.
To start a fresh conversation, omit conversation_id. AskVault creates a new one and returns it.
HTTP status codes
| Status | Meaning |
|---|---|
| 200 | Query processed successfully. Response body is JSON. |
| 401 | Missing or invalid API key. |
| 402 | Out of message credits, or the workspace's model is not on your plan. |
| 403 | Your plan does not include API access (Starter and above). |
| 404 | Workspace not found, or (once rolled out) the conversation_id is not one of your workspace's API conversations. Omit it to start a new conversation. |
| 422 | Validation error, such as a missing query or one over 4,000 characters. |
| 429 | Rate limit exceeded. Read detail and back off. |
| 500 | Server error. Retry with exponential backoff. |
| 503 | Service temporarily unavailable. Retry. |
Every error response includes a JSON body with a detail field describing the problem:
{ "detail": "Validation error: query: Field required" }Log detail for debugging; never show raw error bodies to end users.
Performance
Latency depends on the model your workspace uses, the size of your knowledge base and the length of the answer; a repeated question can be served from the answer cache. For live chat interfaces, use the streaming endpoint so the first words appear as soon as they are written.
Common pitfalls
422 Unprocessable Entity on every request. The request body is using message instead of query. The required field is query.
Empty or placeholder sources on every query. Your workspace may have no indexed content yet. Check the Knowledge page.
Bot answers from training data instead of your content. The workspace knowledge base is the content source. Open Knowledge, verify content is indexed, and re-test.
Conversation context doesn't carry across turns. Send the same session_id for every turn of one end user's conversation.
Answers feel slow. Answer time depends mostly on the workspace's model and answer length. Use the streaming endpoint so users see progress; do not send warm-up queries, which use your limits.
Related guides
- Getting started with the AskVault API
- API authentication
- POST /v1/query/stream
- Rate limits per plan
- Error codes
- Webhooks