POST /v1/query/stream endpoint
Endpoint
POST https://api.askvault.co/v1/query/streamSame request body as /v1/query. Response uses Server-Sent Events (SSE).
Event format
Every line is a plain data: <json> frame: there are no named SSE event: types. Read the done boolean in each payload to tell a token frame from the final frame.
Example
curl -N -X POST https://api.askvault.co/v1/query/stream \ -H "Authorization: Bearer ak_xxx" \ -H "Content-Type: application/json" \ -d '{"query":"What is your refund policy?"}'Returns:
data: {"token":"Our ","done":false}
data: {"token":"refund ","done":false}
data: {"token":"policy ","done":false}
data: {"token":"","done":true,"sources":[{"document_name":"Refund Policy","url":"..."}],"tokens_used":450,"conversation_id":"conv_xxx"}When to use streaming
Three cases:
- Chat UIs. Show the bot's reply as it's typing, like ChatGPT.
- Long responses. Reduce perceived latency.
- Voice TTS streaming. Start speaking before the full answer is ready.
Latency
How fast text starts and finishes depends on the model your workspace uses, the length of the answer and whether tools run. We have not published latency figures. Streaming does not make the full answer faster, but the reader sees progress straight away.
Streaming shows the first words of the answer as soon as they are written, so the visitor is not left staring at an empty box.
Client implementations
Browser: EventSource can't set an Authorization header, so it doesn't work directly against this endpoint: use fetch with a ReadableStream instead (see the full streaming reference for a worked example), or proxy through your backend.
const res = await fetch('/v1/query/stream', { method: 'POST', headers: {/* Authorization, Content-Type */}, body: /* ... */ });const reader = res.body.getReader();const decoder = new TextDecoder();// read chunks, split on "\n\n", parse each "data: {...}" line, check .doneNode.js: Native fetch with a ReadableStream, or a streaming-aware HTTP client.
Python: requests with stream=True and iter_lines(), or httpx streaming.
Error handling
Mid-stream errors arrive as a normal data: frame with done: true:
data: {"error":"Rate limit exceeded","done":true}Client should close the connection and retry with backoff.
Limits
- Same as /v1/query. Auth, rate limits, query length.
- Reconnect. No native reconnect; client retries with new request.
Common pitfalls
Browser blocks the connection. CORS plus credentials issue. Confirm Authorization header allowed.
Stream stalls. Network buffering. Use flush() on your client framework.
Lost tokens. The network dropped mid-stream. There is no resume; send the question again.
FAQ
Does streaming cost more than standard?
No. Same per-query billing.
Can I cancel a stream mid-flight?
Yes, by closing the connection (for example, aborting the fetch). Plan as if the request still counts against your limits.
Does streaming work for skill-triggered responses?
Skill output is short and arrives in batches. Streaming still works but may show as fewer chunks.