Skip to content
Try Free →

POST /v1/query/stream endpoint

Last updated: · 3 min read

Endpoint

POST https://api.askvault.co/v1/query/stream

Same 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

Terminal window
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:

  1. Chat UIs. Show the bot's reply as it's typing, like ChatGPT.
  2. Long responses. Reduce perceived latency.
  3. 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 .done

Node.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.

Was this page helpful?