Get a run
One run: live progress, counters, failure reason, and what it cost. price_cents, billed, included, included_in_trial, trial_tier and charged_cents carry the same values under the same names as the GET /v1/runs row for this run, so a detail screen never has to fetch the list to say "Included in trial" or print a price (E2E5-11).
Request
- Base URL: https://api.hyperresearch.ai
- URL: https://api.hyperresearch.ai/v1/runs/{id}
- Auth: one of:
- HTTP bearer
- API key in cookie hr_session
Path parameters
Response
Run
The project this run is filed under, or null when it is unfiled.
The verbatim research question this run was launched with, not truncated, with its line breaks kept (LF line endings; control characters, trailing spaces and runs of more than two blank lines removed). Null for legacy runs whose question cannot be recovered.
Why a terminal run ended badly: the sanitised, single-line reason from the run log for a failed or aborted run, the gate for a blocked run, null otherwise. An aborted run reads "Stopped by you." for the person who requested the abort and "Stopped by a workspace member." for everyone else; the list row and this field always agree.
The user id that asked for the abort, or null for a run nobody stopped, a run stopped by an unattributed API key, or one stopped before this field existed. Published so a client can say "Stopped by you." on its own terms rather than inferring it from the sentence; failure_reason is already narrowed for the caller.
The raw platform/vendor text behind failure_reason. Present ONLY for a signed-in owner or admin of the workspace, and only when there is one — an API key never receives it. Support material, never customer copy.
Identifies that terminal event in the run log; quote it to support.
One customer-safe sentence saying what a blocked run is waiting for and what to do about it; null on every other status. Branch on blocked_code, not on this string.
The machine gate id behind blocked_on — step:<id>:<check>, verify:<check>, fetch_budget, model_budget or provider:<name>. Stable across copy changes.
Why a blocked run is waiting on US rather than on a person: it is clearing the condition by itself and will carry on with no action from the caller, and nothing has been charged. Present only while a run is waiting; absent or null on every other run, including a block that does need the customer to act. Branch on its PRESENCE, not on the class.
Wall time from start (or creation) to finish; null while the run is unfinished. The SAME number, from the same computation, that the list row serves as duration_ms — a client must not subtract its own timestamps, which is how one run read "15m 57s" here and "16m 0s" on the list (E2E7-11).
How many chapters this run's plan has — the same field, the same name and the same value as the GET /v1/runs row, so a detail page can say "Deep · 4 chapters" without fetching the list. A property of the RUN, not of the step that is moving: step.chapters_total can only answer while a chapter-scoped step is running, which a finished Deep run has none of. Null means not chaptered (or settled before the column existed) — never zero.
The levers.reader_expertise this run was started with (beginner, intermediate or expert), read from its frozen launch packet. Null when the run did not set one, in which case the report is written for an informed non-specialist.
List price of the run at admission, in cents. Null for an auto run not yet classified.
Whether this run has been settled on the usage ledger.
Server truth for "Included in trial": an allowance was claimed at admission. Not a guess from a zero price — a fixture run is also $0 and is not included.
Same value as included; both spellings are published so no client has to pick.
Which included-run allowance was claimed, or null when the run was billable.
True when an operator grant comped this run (migration 0041): it ran for real, at its real price_cents, and its ledger row settles without reaching Stripe. Frozen on the run at admission, so it is unaffected by the grant being revoked or expiring later. Never inferred from a zero amount — a comped run’s ledger row carries the full price.
What the usage ledger actually metered for this run, refunds included. Null until a ledger row exists, which is NOT the same as zero. Exactly the field and the value GET /v1/runs publishes for this run.
Word count of the finished report; null while there is no report. The SAME field, name and value the GET /v1/runs row and the report cards publish — the run detail was the one screen that showed the report and would not say how long it was (E2E8-06).
The newest run in this workspace asking the same question, or null when this run IS that run. Label a run “Earlier version” if and only if this is set. Grouped by normalised question text, or by an explicit rerun parent — never by project, which is a body of sources and says nothing about which report replaces which (E2E8-10).
Stable key for the version group, so a client can bucket rows in one pass.
True when this run was a DRY RUN: the orchestration was real but the model provider and the fetch/search vendors were mocked, so the report is synthetic and the price is $0. Server truth (the run’s dry_run channel), never inferred from a zero price — a trial run and a fixture run are also $0 and are not dry. Always false in production, where dry runs cannot be created.
Example response
{
"levers": {
"purpose": "decide",
"report_language": "zh",
"reader_expertise": "expert"
}
}Changes
No recorded changes to this operation across all 1 revision of this API.