Research reports
POST /v1/research answers a question with a written report from the live web. Each cited sentence links to the page it came from, with the time the page was read.
Start a report
Send your question as input and choose a depth. The call answers 202 at once with the report’s id and its price. Create a key under Agents & API in your workspace. Authentication
Read the report
Read GET /v1/research/{id} until status is completed. A quick report takes about a minute, a standard report about four minutes, and a deep report about five. To follow the work as it happens, open GET /v1/research/{id}/events: it is a server-sent event stream that names each stage and each page as it is read, and Last-Event-ID resumes it.
A completed report, cut short:
| Field | What it holds |
|---|---|
status | queued, running, completed, failed, cancelled, or payment_required. |
stage | queued, planning, searching, reading, writing, checking, or done. |
report.content | The text, with a [1] marker after each cited sentence. For JSON output, report.structured holds the object. |
report.citations | One entry per cited sentence: the page, when it was read, the passage, and where the sentence sits in content (start and end). |
report.sources | Every page read for the report, with its read time. |
usage | The searches run, the pages read, and charged_usd, the price taken for this report. |
The same two calls in Python:
POST /v1/research/{id}/cancel stops a report. GET /v1/research lists your account’s reports, newest first.
Price and retries
A report is $0.10 at quick depth, $0.30 at standard, and $1 at deep. The price comes out of your balance once, when the report is delivered. A canceled report is not charged. Send an Idempotency-Key header (at most 128 characters) to retry safely: the same key and body return the same report.
What you can send
| Field | What it does |
|---|---|
input | The question, in plain words. Up to 15,000 characters. |
depth | quick, standard (the default), or deep. Each depth has one price and reads more of the web than the one before it. |
output | {"type": "text"} for markdown (the default), or {"type": "json", "schema": {...}} for JSON that matches your JSON Schema. |
length | short, standard, or long. It sets how long the text is. |
language | The report’s language. By default it is the question’s language. |
include_domains, exclude_domains | The sites to read, or the sites to leave out. |
webhook | {"url": "https://..."}. SpecStream calls it when the report ends, signed with your account’s webhook secret. |
metadata | Up to 16 keys of your own. They come back on the report. |
On MCP
research_price shows the price of each depth. start_research starts a report once the user approves that price as confirm_max_cents. get_research reads it until it is completed, cancel_research stops it, and list_research lists the account’s reports. Set up MCP
When a call stops
| Status | What happened |
|---|---|
401 | No key or token. Send Authorization: Bearer with your API key. |
402 | insufficient_balance: the balance doesn’t hold the report’s price. Add balance under Settings, Usage and billing, then send it again. |
404 | No report with this ID on your account. |
409 | The Idempotency-Key was used with another body. Send a new key. |
422 | A field is wrong. The reply names the field and the problem. |
429 | The account used its calls for the minute. Wait the seconds in Retry-After and send it again. |