Streaming AI Search
Stream the AI Search summary over the same POST /desearch/ai/search as the first call, when you want progressive output instead of one JSON body.
Who this page is for
Humans
You already got a 200 with "streaming": false on the Search API first-call page. Flip to "streaming": true on REST when a UI or agent should show the summary as it is written. Read cost from response headers, not the stream body.
Agents / tool authors
Prefer a non-stream first call for a single tool result (search plus optional completion in one JSON object). Use streaming only when the runtime can consume an HTTP stream (SSE) and you need progressive summary output. Official SDKs (ai_search / aiSearch) currently force non-stream. Call REST for "streaming": true.
When to stream vs not
| Goal | Setting | Where |
|---|---|---|
| One JSON body for first success or tests | "streaming": false | Search API first call |
| Progressive summary over the wire | "streaming": true | This page |
OpenAPI default for streaming is true. Always set the boolean explicitly so you do not accidentally stream into a client that expects one JSON object.
REST request
- Method / path:
POST /desearch/ai/search - Base:
https://api.desearch.ai - Auth:
Authorization: $DESEARCH_API_KEY(raw key in examples). See Auth and API keys. - Accept:
text/event-stream(live Content-Type on success istext/event-stream) - Body: same fields as the first call (
prompt,tools, optionalcount, date filters,result_type) plus"streaming": true - For a streamed summary path, keep
result_typeatLINKS_WITH_FINAL_SUMMARYunless you have a verified reason to change it
curl (buffering off)
Capture response headers (-D - or -i) so billing headers are visible. Do not commit the key.
SSE wire format (live)
Verified against a live streaming: true response (2026-09-24):
| Fact | Observed |
|---|---|
| HTTP status | 200 |
Content-Type | text/event-stream |
| Frame shape | data: <json> lines, blank line between frames |
event: / id: fields | Not present |
| Cost / usage in body | Not present (headers only) |
Event type order
- One
searchevent:{"type":"search","content":[ ... result objects ... ]}. Result objects includetitle,link,snippet, andhighlights(a list). Other fields may appear. Do not require fields you have not verified. - Many
textevents:{"type":"text","role":"summary","content":"<token chunk>"}(incremental summary tokens). - One final
completionevent:{"type":"completion","content":"<full summary string>"}.
Parse only data: lines. Read JSON type to decide how to handle each frame. Do not invent named SSE event: channels.
Sample frames (redacted / shortened)
Concatenate successive text chunks where role is summary for a progressive UI. Prefer the final completion.content as the full summary string when the stream ends cleanly.
SDKs: use REST for streaming
| Package | Version checked | Stream support |
|---|---|---|
desearch-py | 1.2.1 | ai_search hardcodes "streaming": false. No stream iterator. Use REST. |
desearch-js | 1.5.0 | aiSearch always sends streaming: false (even if the caller adds the field). Use REST. |
Do not document SDK stream helpers, async generators, or streaming=True as a working SDK path until a published package ships them and they are re-verified.
Non-stream first call with SDK tabs stays on the Search API guide.
Billing on stream
Successful billable responses expose cost only through headers:
| Header | Meaning |
|---|---|
X-Desearch-Cost-Usd | Cost in USD for the request |
X-Desearch-Usage-Count | Billable usage units |
X-Desearch-Service | Pricing service / endpoint key |
X-Desearch-Currency | Currency (for example USD) |
Related headers often seen with the stream: cache-control: no-cache, x-proxy-buffering: no.
Streaming responses keep their body shape as the SSE frames above. Do not claim the stream JSON includes cost_usd. This page does not list product dollar rates.
Failures
Before the stream body, or instead of one
Align with Rate limits and errors:
| Status | Meaning | What to do |
|---|---|---|
401 | Missing or invalid key | Fix auth |
402 | Out of credits | Top up in Console |
422 | Invalid parameters | Fix the body against the API reference |
429 | Rate limited | Exponential backoff. Do not tight-loop |
5xx | Server failure | Short delay and retry. Check status |
Mid-stream disconnect
If the connection drops mid-stream, treat the result as incomplete. Retry with the same policy as other failed requests (rate-limit guide). A retry is a new request and may be billable again. Do not invent SSE error type values or status codes inside the stream channel. None were verified in the live smoke for this page.
Verify
- Non-stream first call already works (
streaming: false) - Stream request uses
curl --no-buffer(or equivalent) and"streaming": true - Response
Content-Typeistext/event-stream - Frames are
data: {json}only. Order issearch, thentextrepeated, thencompletion - Billing is read from
X-Desearch-*headers, not the body - No SDK stream helper is assumed
Next
- Search API first call (
streaming: false) - Which endpoint
- AI Contextual Search API reference
- Rate limits and errors
- Auth and API keys