Create a run
const url = 'https://api.hyperresearch.ai/v1/runs';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"query":"What changed in EU AI Act enforcement in 2026?","tier":"light","clarify":"ask","levers":{"register":"teach","inference_depth":"surface","domain_notes":"example","response_format":"example","required_section_headings":["example"],"citation_style":"numbered","purpose":"decide","report_language":"zh","reader_expertise":"beginner"},"profile":"value","budget":{"fetch_usd_max":1,"sources_max":1},"vault":{"reuse":"all","tags":["example"],"reuse_tags":["example"],"reuse_scope":"off"},"project_id":"proj_01J9ZQ7V6H0000000000000000","webhook_url":"https://example.com","metadata":{"additionalProperty":"example"}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.hyperresearch.ai/v1/runs \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "query": "What changed in EU AI Act enforcement in 2026?", "tier": "light", "clarify": "ask", "levers": { "register": "teach", "inference_depth": "surface", "domain_notes": "example", "response_format": "example", "required_section_headings": [ "example" ], "citation_style": "numbered", "purpose": "decide", "report_language": "zh", "reader_expertise": "beginner" }, "profile": "value", "budget": { "fetch_usd_max": 1, "sources_max": 1 }, "vault": { "reuse": "all", "tags": [ "example" ], "reuse_tags": [ "example" ], "reuse_scope": "off" }, "project_id": "proj_01J9ZQ7V6H0000000000000000", "webhook_url": "https://example.com", "metadata": { "additionalProperty": "example" } }'Validates the request, checks the tier against the plan, the workspace concurrency limit and the account spend cap, fixes the price, writes the D1 index row, and starts the research-run Workflow.
Authorizations
Section titled “Authorizations”Parameters
Section titled “ Parameters ”Header Parameters
Section titled “Header Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”object
Example
What changed in EU AI Act enforcement in 2026?The tier to run at: light ($9, one focused question or a narrow topic) or premier ($49, shown as “Deep” - a broader question across several research sections). Omitted, it is light. brief, full, dissertation and auto are not offered and are refused with 400 tier_not_offered.
Example
lightWhat to do about an ambiguous question, decided BEFORE anything is reserved or charged. ask assesses the question and, when it earns it, holds the run at clarifying with at most three questions for a person to answer at POST /v1/runs/{id}/clarify; left unanswered for 30 minutes it starts by itself on the stated assumptions (or closes without charge if it cannot be admitted then). auto assesses but never waits: the run starts immediately on those assumptions, which its report then names. Under ask and auto a query with nothing to research in it (a greeting, a test string) is held at clarifying and asked what to research; unanswered, it closes without charge. off is a hard bypass: no assessment and no interview of any kind — the run starts at once on the query as written, and a query with nothing to research in it is refused with 400 query_not_research instead of being held. Omitted, a console run defaults to ask and every other channel to auto, unless the workspace sets clarify_default.
Example
autoobject
Deprecated. Still accepted and stored on the run, but the research planner sets its own depth for each question and no longer reads this value. Omit it.
Deprecated and ignored. Still accepted so existing callers keep working, but no longer stored on the run: every report uses the same citation markers whatever this says. Omit it.
What the report is for. decide opens with the answer and what it means for the decision, sets out the trade-offs and closes with a recommendation; understand explains the subject and its mechanisms without pushing a recommendation; brief_someone makes the opening summary a stand-alone brief you can forward. It changes how the report is organised and summarised, never what it researches, claims or cites, and it does not change the price, the sources or the run time. Omitted, the report is organised as before.
Example
decideThe language the report is written in, as a language tag (en, zh, ja, ko, fr, …) or a bilingual pair (zh+en). Omitted, the report follows the language the question asks for, or the language it is written in. Headings and the labels the pipeline adds are localised for English, Chinese, Japanese and Korean, and are in English for other languages.
Example
zhWho the report is written for. beginner defines technical terms and acronyms in plain words and explains the background a newcomer needs; intermediate uses the field’s standard terms and defines only specialist ones; expert uses the field’s terminology without definitions and spends the words on specifics. It changes how the report explains things, never what it researches, claims or cites, and it does not change the price, the sources or the run time. Omitted, the report is written for an informed non-specialist, as before.
Example
expertobject
Deprecated. Still accepted, and still applied as a ceiling on paid page fetching and search for this run, but a low value can leave a run short of sources and stop it before it finishes. Must be greater than 0. The tier already bounds this spend and the price does not change with it. Omit it.
Deprecated. Still accepted, and still applied as a cap on how many sources this run reads, up to the tier ceiling. A value below the tier’s source floor stops the run at the source gate, and the price does not change with it. Omit it.
object
Restrict vault-first reuse to notes carrying ALL of these tags. Set by the server for a project run (project:<id>). An unfiled run reuses nothing unless reuse_scope is workspace, which clears this list.
Which slice of the vault this run may reuse evidence from, before any fetching. workspace reads the whole workspace vault; a candidate is only accepted when it clears a relevance, topic-overlap and freshness gate, and workspace reuse can never supply more than a quarter of the run’s source floor. project restricts reuse to the run’s own project and requires project_id. off disables vault-first reuse entirely — every source is fetched fresh. Omitted, a filed run defaults to project and an unfiled run to off: an unfiled run reads the workspace vault only when workspace is named here (vault.reuse: true alone does not opt in). Either way the run writes its notes to the workspace vault, and filing it under a project later moves them into that project. This is a shorthand over vault.reuse / vault.reuse_tags, which it overrides.
Example
workspaceFile this run under a project in the same workspace. The run’s notes are tagged project:<id> and vault reuse is scoped to that tag. Omit for an unfiled run.
Example
proj_01J9ZQ7V6H0000000000000000object
Responses
Section titled “ Responses ”Run queued
object
clarifying when the question was ambiguous enough to be worth asking about, or was not a research question at all. The run exists at its final id and is waiting at POST /v1/runs/{id}/clarify; nothing has been reserved or charged, so price_cents is null. aborted is only ever answered by POST /v1/runs/{id}/clarify, for an interview that ran out of rounds without finding a research question: that run started nothing, reserved nothing and claimed no included run.
object
object
The named dimension this question is about (scope, time_window, geography, …). Answer by axis, not by position.
What the run will do if this question is not answered. Shown behind “You decide” and in the skip-all confirmation, and printed in the report’s Assumptions paragraph.
The span of the customer’s own question that prompted this one, when it could be quoted verbatim.
object
The literal you_decide when the customer left this to us; the assumption then records the decision.
Every default this run is proceeding on — verbatim the sentences its report prints.
When an unanswered interview times out; what happens then is on_timeout. Null once the interview is settled.
Present while status is asking: what happens at expires_at if nobody answers. start admits the run on its stated assumptions (or closes it without charge if it cannot be admitted then — spend cap, no payment method); close ends it without starting and without charge, which is what an interview that found nothing to research does.
A sentence about the interview rather than about the question: that the ambiguity assessment could not be made (resolution: "unassessed"), that nothing has started while we ask what to research, or that the time-box closed the run without charge.
Example
{ "id": "run_01J9ZQ7V6H0000000000000000", "status": "queued", "tier": "auto", "clarification": { "status": "asking", "on_timeout": "start", "resolution": "answered" }}Headers
Section titled “Headers”Example
"reads";q=60;w=60The quota policy this request was counted against (draft-ietf-httpapi-ratelimit-headers): "<bucket>";q=<requests>;w=<window seconds>, e.g. "reads";q=60;w=60. Buckets: reads 60/min, status 600/min, creates 10/min, writes 20/min per credential; public 300/min per network on keyless routes.
Example
"reads";r=57;t=41Remaining quota in the current window: "<bucket>";r=<remaining>;t=<seconds until reset>, e.g. "reads";r=57;t=41.
Requests allowed per window in this bucket (legacy form of RateLimit-Policy).
Requests left in this window (legacy form of RateLimit).
Unix time (seconds) when the window resets.
Which bucket counted the request: reads, status, creates, writes or public.
Invalid request
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Authentication failed
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Spend cap exceeded
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Insufficient scope or plan
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Not found
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Idempotency-Key reused with a different body
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Rate limited or over quota
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}Headers
Section titled “Headers”Seconds to wait before retrying. Always present on a 429.
Example
"reads";q=60;w=60The quota policy this request was counted against (draft-ietf-httpapi-ratelimit-headers): "<bucket>";q=<requests>;w=<window seconds>, e.g. "reads";q=60;w=60. Buckets: reads 60/min, status 600/min, creates 10/min, writes 20/min per credential; public 300/min per network on keyless routes.
Example
"reads";r=57;t=41Remaining quota in the current window: "<bucket>";r=<remaining>;t=<seconds until reset>, e.g. "reads";r=57;t=41.
Requests allowed per window in this bucket (legacy form of RateLimit-Policy).
Requests left in this window (legacy form of RateLimit).
Unix time (seconds) when the window resets.
Which bucket counted the request: reads, status, creates, writes or public.
Internal error
object
object
Example
{ "error": { "type": "invalid_request", "code": "missing_api_key", "request_id": "req_01J9ZQ7V6H0000000000000000" }}