200 with the parsed Envelope. No polling, no webhook.
Sync is the default for the hello-world case: a request with one surface and no webhook runs synchronously without any flag. Multi-surface requests, requests with a webhook, or ?mode=async use the durable 202 path instead — see asynchronous requests.
Three ways to go synchronous
Just send one surface
A
POST /v1/search with exactly one surface and no webhook is synchronous
by default.Force it explicitly
Add
?mode=sync or send the header Prefer: wait=30 to pin the inline
path.Use the surface alias
POST /v1/search/:surface (e.g. /v1/search/chatgpt) accepts prompt (an
alias of query) and a flat country.All paths return the same shape. The alias is just a shorter, single-surface
form of the same call.
Request
prompt and flat country:
cURL
Response
You get200 with the parent id, its rollup status, and the full Envelope for each child — the same four-section Envelope a child returns from GET /v1/jobs/:id:
The parent id for this submission.
status is the rollup across children
(completed, partial, or failed).One full Envelope per child. Each has four sections:
job, provenance,
answer, and evidence (plus optional html and credits). When
provenance.surfacePresent is false and a surface_absent warning is
present, the surface returned nothing. The capture still completes with an
empty answer and costs no credits.Built-in retry on transient failures
A sync call blocks on a single live capture, so a transient upstream hiccup — a timeout or a5xx from the surface — would otherwise surface immediately as an
error. To keep the default single-surface path reliable, the capture step gets a
small bounded server-side retry on transient failures before the response
returns, within the request’s wait budget. Only genuinely transient failures are
retried; a deliberate stop (a captcha or login wall) or a validation error is
returned right away, never retried.
This is a small budget scoped to the sync wait. Asynchronous jobs get the
full durable retry budget of the background Workflow instead — up to 8
bounded steps — so for large fan-outs or flaky surfaces, prefer
async. Retries never double-bill: a capture is charged
only once, on success.
Errors specific to sync
Because the call blocks on a live capture, two error paths matter more here than in async.429 CONCURRENCY_LIMIT_EXCEEDED
429 CONCURRENCY_LIMIT_EXCEEDED
Your key has a sync concurrency budget — the number of blocking captures
allowed at once. When too many sync calls are already inflight, new ones get
429 CONCURRENCY_LIMIT_EXCEEDED. Wait for the Retry-After window, then
retry — or switch to ?mode=async. The response also carries
X-Concurrency-Limit, X-Concurrency-Running, and X-Concurrency-Queued
so you can back off precisely. See concurrency & rate
limits.504 SURFACE_TIMEOUT
504 SURFACE_TIMEOUT
If the surface doesn’t respond within the capture window, you get
504 SURFACE_TIMEOUT. This is a transient upstream timeout — retry the request.
No credits are charged for the failed capture, since captures are billed
only on success.All
429s also carry Retry-After plus X-RateLimit-Limit,
X-RateLimit-Remaining, and X-RateLimit-Reset. Honor Retry-After before
retrying.When not to use sync
Next steps
Asynchronous requests
Fan out across surfaces and regions without blocking.
Concurrency & limits
Understand the sync budget, rate limits, and the headers to back off on.