GET /v1/routines/waits/{token}
The link of a `wait` step with `token: true` (`run.wait_urls.<step id>`, routine.schema.json). Send it to the person who should answer: no API key and no login are needed, the link is the credential. A browser (`Accept: text/html`) gets a page with the step's `prompt` (title, body, image, link) and Approve and Reject buttons; `?decision=approve` or `?decision=reject` preselects one, for buttons in a Slack or email message (the person still confirms, so link previews and mail scanners that fetch the URL answer nothing). Programs get the `RoutineWait` JSON. The link names one run and step of one project and is signed by the node; it works once, while the step waits, and for at most 7 days after the step started waiting. The run's end, the step's own deadline or a signal sent through the API ends it too. Any link that is malformed, signed for another run, step or project, or whose run is no longer kept answers the same 404 `wait_link_invalid`. Answers carry `Cache-Control: no-store` and `Referrer-Policy: no-referrer`, and the link never appears in your organization's request log.

Path Parameters

token string required path
The link's token, `<run id>.<step id>.<signature>` (32 base64url characters), from `run.wait_urls.<step id>`. Anything else answers `wait_link_invalid`, so a link cut short in a message still gets the page that says so.
Example: "run_01m6f0re3gzz9kvb26hebdcd0x.approve.q3Zr0wq9mXk3o1yJb7vH2cT5dN8pLa4e"

Query Parameters

decision string optional query
Preselect a decision on the page (HTML only); nothing is answered until the person confirms.

Responses

200 The step the link answers, as JSON, or the page for a browser.
application/json
object string REQUIRED
Enum: routine_wait
status string REQUIRED
waiting: it takes an answer. pending: the step has not started waiting. answered: through a link or a signal. timed_out: its deadline passed. expired: 7 days after it started waiting. ended: the run ended, or the step was skipped or canceled, before an answer.
Enum: waiting, pending, answered, timed_out, expired, ended
run_id string REQUIRED
run_status string REQUIRED
Enum: queued, running, succeeded, failed, canceled
routine_id string REQUIRED
routine_name string | null
step_id string REQUIRED
step_name string | null
prompt object | null REQUIRED
The step's evaluated prompt while it waits, and after an answer while the node still holds the run (null once the run is only in the run store).
title string
body string
image string (uri)
link string (uri)
dropped string[]
Array of: string
waiting_since string (date-time) | null
expires_at string (date-time) | null
While the step waits; its own deadline may end it sooner.
answer object | null REQUIRED
Once answered. `decision` is null for a signal sent through the API without one.
decision string | null
Enum: approve, reject, null
approved boolean | null
comment string | null
via string
Enum: link, signal
answered_at string (date-time) | null
400 The request failed validation (`invalid_request`, `invalid_url`).
404 The link is not valid (`wait_link_invalid`).
429 A rate, concurrency or quota limit applies (`rate_limited`, `concurrency_limited`, `quota_exceeded`).
500 Something failed inside B3OS (`internal`). Retry with backoff.
503 The node or the product is not available right now (`node_unavailable`, `product_unavailable`, `capacity_unavailable`).
curl -X GET 'https://beta-api.b3os.org/v1/routines/waits/run_01m6f0re3gzz9kvb26hebdcd0x.approve.q3Zr0wq9mXk3o1yJb7vH2cT5dN8pLa4e' \  -H 'Authorization: Bearer YOUR_API_TOKEN'
const response = await fetch('https://beta-api.b3os.org/v1/routines/waits/run_01m6f0re3gzz9kvb26hebdcd0x.approve.q3Zr0wq9mXk3o1yJb7vH2cT5dN8pLa4e', {  method: 'GET',  headers: {      "Authorization": "Bearer YOUR_API_TOKEN"  }});const data = await response.json();console.log(data);
import requestsheaders = {    'Authorization': 'Bearer YOUR_API_TOKEN'}response = requests.get('https://beta-api.b3os.org/v1/routines/waits/run_01m6f0re3gzz9kvb26hebdcd0x.approve.q3Zr0wq9mXk3o1yJb7vH2cT5dN8pLa4e', headers=headers)print(response.json())
200 Response
{  "object": "routine_wait",  "status": "waiting",  "run_id": "run_01m6f0re3gzz9kvb26hebdcd0x",  "run_status": "running",  "routine_id": "rtn_01m5t6vhkw4a8fa4tb5w4ffz37",  "routine_name": "launch-card",  "step_id": "approve",  "step_name": "Approve the card",  "prompt": {    "title": "Post the launch card to",    "body": "The card for 0.4.0 is below. Approve posts it; Reject stops the run here.",    "image": "https://usercontent.beta.b3os.org/render/art_01m6f0rf6q8f3d8wq7xr7d1f3p/card.png"  },  "waiting_since": "2026-11-02T22:10:04.211Z",  "expires_at": "2026-11-09T22:10:04.211Z",  "answer": null}
Ask a question... ⌘I