POST /v1/parallel/tasks/runs
Parallel Task runs: deep research as a job, lite to pro, billed at Parallel's price only when the run completes.
Parallel Task runs. Parallel's Task API does deep research and enrichment: you give it a question or a JSON object and, if you like, the shape of the answer, and it searches and reads the web and answers with citations. A run takes from about 10 seconds (lite) to about 10 minutes (pro), longer than any request can stay open. So a run is a job:
- 01
POST /v1/parallel/tasks/runscreates it and answers at once with a run object; - 02
GET /v1/parallel/tasks/runs/{id}reads it until itsstatusiscompleted(orfailed, orcancelled), orGET .../{id}/eventsstreams its progress; - 03
GET /v1/parallel/tasks/runs/{id}/resultfetches the answer.
The field names are Parallel's, so Parallel's Task API docs apply to the body you send, within the limits below.
What you send goes to Parallel, a third party, which may use it and the answer to improve its services and stores data in the US. Do not send what you would not share with Parallel. See Data.
Who can use it
An organization API key of a paid organization: a key you created in API keys for an organization that has added paid credit. Playground and evaluation keys, and organizations still on the free trial, get 403 forbidden: "Parallel Task runs need an organization API key from a paid organization: create one in API keys and add paid credit in Billing". Nothing is reserved or sent.
Task runs are billed to your organization's credit. A key limited to your own provider keys or to a routing policy cannot spend it, so a create with such a key is a 403 forbidden too: "This API key is limited to its own provider keys or a routing policy, and Parallel Task runs are billed to marketplace credit: use an organization API key without that limit. A routing policy set on the organization or workspace applies to every key, so an owner must change it in the console". Nothing is reserved or sent. Reading runs is unchanged.
Prices
Parallel's list price for the processor, per run, with no markup. A run is billed when Parallel completes it; see the rules below for runs that never end or that a restart interrupts, and read the run's cost for what was charged:
| Processor | Price per run | Per 1,000 runs | Typical time |
|---|---|---|---|
lite | $0.005 | $5 | 10 s to 2 min |
base | $0.01 | $10 | 15 s to 3 min |
core | $0.025 | $25 | 1 to 5 min |
core2x | $0.05 | $50 | 1 to 10 min |
pro | $0.1 | $100 | 2 to 10 min |
The ultra processors are not offered. The price of one output field or twenty is the same: Parallel prices the run, not the fields.
How the money moves:
- On create, the gateway holds the run's price from your credit, as it holds any request's maximum cost (see Pricing). Without that much credit the create is the usual 429
insufficient_quota, and nothing runs. - When Parallel says the run is
completed, the hold becomes the charge: the run's price, to the micro-dollar. - When Parallel says the run
failedor wascancelled, or that it needs an action (action_required), the charge is $0. - If no end arrives within 2 hours, the run is given up on with the error
run_timeout. If Parallel still reports itqueuedorrunning, Parallel has not completed it and the charge is $0. Only if we cannot get an answer from Parallel at that point is it charged its price (the hold), since it may have completed. - If the gateway that follows your run restarts while it is running, the run is charged its price (the hold) when the gateway comes back, as any request a restart cuts short is. If Parallel then completes it, that is its price anyway. If Parallel still reports it running after 2 hours, the charge is credited back, but only once you read the run after those 2 hours: it then shows as an
adjustmentcredit in Billing, and the run'scostreads 0. If Parallel fails it, the charge stands: contact support with the run'sidto have it reconciled. - The run's
costis always what you were charged;error.messagenever says.
The charge appears in GET /v1/usage & /v1/generation as one attempt: provider parallel, model parallel:task:<processor>, the price as server_tool_fee_usd.
Create a run
curl https://api.routerplus.com/v1/parallel/tasks/runs \
-H "Authorization: Bearer $TM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"processor": "lite", "input": "Which RFC defines HTTP semantics, and when was it published?"}'{"id": "ptrun_6f0c1e2d3a4b5c6d7e8f901a2b3c4d5e", "object": "parallel.task_run", "status": "queued",
"processor": "lite", "created_at": "2026-11-06T00:26:54.676Z", "finished_at": null, "cost": null, "error": null}The body, at most 64 KB:
| Field | Required | What it takes |
|---|---|---|
processor | yes | lite, base, core, core2x or pro |
input | yes | A string, or a JSON object; at most 32,000 characters as JSON |
task_spec | no | {"output_schema": ..., "input_schema": ...}, at most 16 KB as JSON. Each schema is a string (a text description), {"type": "json", "json_schema": {...}} or {"type": "text", "description": "..."}. output_schema may also be {"type": "auto"} (deep research), on pro only. output_schema is required when task_spec is set |
enable_events | no | true or false: whether Parallel records progress events for /events. Parallel turns them on by default for pro |
Refused with a 400 invalid_request that names the field, before anything is held or sent:
| Field | Why |
|---|---|
webhook | Not supported: read the run, or stream its /events |
mcp_servers | A run cannot call MCP servers through RouterPlus |
previous_interaction_id | Runs cannot be chained |
source_policy | Not supported yet |
advanced_settings | Not supported |
memory_scope_key | RouterPlus does not use Parallel memory |
metadata | RouterPlus sets the run's metadata itself |
| any other field | Unknown |
A processor of ultra, ultra2x, ultra4x or ultra8x is a 400 that says it is not offered. So is a JSON schema no answer can satisfy, such as an empty enum or a required field that properties does not define: Parallel accepts such a run and it never ends (in our test one was still queued after an hour).
Read a run
GET /v1/parallel/tasks/runs/{id} answers the run object:
| Field | Meaning |
|---|---|
id | Our id, ptrun_ and 32 hex digits. Parallel's own run id is never shown |
status | queued, running, completed, failed or cancelled |
processor | As sent |
created_at, finished_at | RFC 3339 times; finished_at is null until the run ends |
cost | USD, once the run is settled: what you were charged (the price, or 0); null before. The one source for the charge |
error | null, or {"code", "message"} once a run ends without completing: run_failed, run_cancelled, action_required, run_timeout or run_expired. Read cost for what it was charged |
A run is shown finished only once its charge is recorded, so a completed run always has its cost. Poll every 5 to 10 seconds. A run slower than its typical time is still working; nothing speeds it up, and after 2 hours it ends with run_timeout.
An unknown id, a malformed id and a run of another organization all get the same 404 not_found: run "<id>" not found.
Fetch the result
GET /v1/parallel/tasks/runs/{id}/result, for a completed run:
{"id": "ptrun_6f0c...", "status": "completed",
"output": {"type": "json", "content": {"output": "RFC 9110, published in June 2022."},
"basis": [{"field": "output", "citations": [{"url": "https://www.rfc-editor.org/rfc/rfc9110.html", "title": "RFC 9110: HTTP Semantics", "excerpts": ["..."]}],
"reasoning": "...", "confidence": "high"}]}}output.typeistextorjson;contentis a string or the JSON youroutput_schemadescribes.basiskeeps, per field, itscitations(url,title,excerpts), thereasoningand theconfidence. Parallel's other fields are not passed on.- The result is fetched from Parallel each time you ask: RouterPlus keeps no output. We have seen Parallel serve a result unchanged for an hour, not longer: save the result when you fetch it. The
proresults we tested were 180 to 280 KB; a result over 2 MB is a 502result_too_large. - For a run that is not
completed, the answer is a 409run_not_completewith the status. It does not wait: read the run until it iscompleted, then fetch the result.
Stream progress
GET /v1/parallel/tasks/runs/{id}/events streams Server-Sent Events for up to 570 seconds, then closes; open it again to follow a long run. The stream starts with the run's state and, while the run is active, replays the progress recorded so far. Only these events are passed on:
| Event | Data |
|---|---|
task_run.state | {"type", "run"}: our run object, as a read shows it |
task_run.progress_msg.* (plan, search, tool_call, result, exec_status, ...) | {"type", "message", "timestamp"} |
task_run.progress_stats | {"type", "source_stats": {"num_sources_considered", "num_sources_read"}} |
Other events and progress lines over 16 KB are dropped. The final state event never carries the output: fetch it from /result. At most 5 streams per organization are open at once (a sixth is a 429 rate_limit). When you disconnect, the gateway stops reading from Parallel.
Cancel
POST /v1/parallel/tasks/runs/{id}/cancel answers 409 cancel_unsupported: "Parallel Task runs cannot be stopped once created; this run continues and is billed when Parallel completes it; see Limits for runs that never end". Parallel offers no way to stop a Task run (we tried its cancel and DELETE routes on queued and running runs: neither exists, and the runs completed). Nothing changes; the run goes on and is billed when Parallel completes it (see Limits for runs that never end). A run that is still queued long after its typical time will not be stopped either: it keeps one of your 5 active slots until it ends or reaches 2 hours, and then ends with run_timeout at $0 if Parallel still reports it active.
Limits
| Limit | Value | Over it |
|---|---|---|
| Creates per organization per minute | 10 | 429 rate_limit: wait retry-after |
| Result fetches and event streams opened per organization per minute | 60 | 429 rate_limit: wait retry-after |
Active runs (queued or running) per organization | 5 | 429 rate_limit: "5 Parallel Task runs already active". A run keeps its slot until it ends or reaches 2 hours |
| Open event streams per organization | 5 | 429 rate_limit |
| Request body | 64 KB | 400 invalid_request |
input as JSON | 32,000 characters | 400 invalid_request |
task_spec as JSON | 16 KB | 400 invalid_request |
| Result | 2 MB | 502 result_too_large |
| Event stream | 570 seconds | The stream ends; open it again |
| A run's life | 2 hours | run_timeout: $0 if Parallel still reports it active, its price if Parallel could not be reached |
Errors
| Status | error_type | When |
|---|---|---|
| 400 | invalid_request | A field refused or over its limit (the message names it) |
| 400 | upstream_rejected | Parallel refused the run: "Parallel refused the run (HTTP 422)". Not billed |
| 403 | forbidden | Not an organization key of a paid organization: create one in API keys and add paid credit. Or, on a create, a key limited to its own provider keys or a routing policy: use one without that limit (a policy on the organization or workspace applies to every key: an owner changes it in the console) |
| 404 | not_found | No such run for your organization. On every /v1/parallel/tasks/runs path, even a create, it means the gateway you called does not serve Task runs (the same 404 as any unknown route): ask support to turn them on |
| 409 | run_not_complete | /result for a run that is not completed: read the run, then retry |
| 409 | cancel_unsupported | /cancel: runs cannot be stopped |
| 429 | rate_limit | A per-minute or active-run limit, or 5 open streams: wait retry-after |
| 429 | insufficient_quota | Not enough credit to hold the run's price |
| 502 | upstream_error | Parallel did not accept the run or return the result. A failed create is not billed |
| 502 | result_too_large | The result is over 2 MB |
| 503 | provider_unavailable | "turned on but not configured": Task runs are turned on for the gateway you called, but our Parallel key or its address is not in place yet; ask support, retrying will not help until it is configured. Or Parallel is refusing our key or limiting new runs. Not billed |
| 503 | gateway_error | Our ledger or run store is briefly unavailable: nothing was held or sent; retry after retry-after. If the message says the runs have no price, retrying will not help: contact support |
Parallel's own error text is never passed on.
Data
- What you send in
inputandtask_specgoes to Parallel, a third party, with our Parallel key. Under Parallel's standard terms it may use inputs and outputs to improve its services; until our account terms with Parallel are settled, treat runs as retained and possibly used for training by Parallel. Parallel stores data in the US. See Data policy. - RouterPlus keeps, per run, ids, the processor, the status, an error code, the cost and times: no input, schema, output, event or Parallel text. The create body is logged only if your organization has request logging on, as any request is. Results and events are never logged or kept.
- RouterPlus never sends
memory_scope_key,webhook,mcp_serversorprevious_interaction_id.
Markdown source for agents: /docs/parallel-tasks.md · index at /llms.txt