Tasks
Durable, joinable tasks with one recorded result, plus resource-aware admission.
All paths are relative to the API base URL (https://api.getrunstate.com) and require Authorization: Bearer <api key>. See the API overview for authentication, idempotency and the error envelope.
GET /tasks
Section titled “GET /tasks”GET /v1/spaces/{spaceId}/tasksList tasks with optional scopeId/state filters.
- Key permission:
coordination_read
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
Query parameters
| Name | Type | Notes |
|---|---|---|
scopeId |
string (uuid) | |
state |
string | |
limit |
integer |
Responses
| Status | Meaning |
|---|---|
200 |
Tasks |
curl -X GET "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks" \ -H "Authorization: Bearer $RUNSTATE_API_KEY"POST /tasks
Section titled “POST /tasks”POST /v1/spaces/{spaceId}/tasksSubmit durable work; idempotent create-or-join by taskKey+fingerprint.
- Key permission:
coordination_write - Idempotency-Key header: required
- TypeScript SDK:
run.mailbox(name).submit() - Python SDK:
run.mailbox(name).submit()
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
Request body (JSON)
| Field | Type | Required | Notes |
|---|---|---|---|
scopeId |
string (uuid) | yes | |
mailboxId |
string (uuid) | yes | |
taskKey |
string | yes | length 1–512 |
input |
any JSON | no | |
deadline |
string (date-time) | no | |
subscriberId |
string | no | |
requirements |
object | no | |
requirements.pools |
array of object | no | |
requirements.pools[].name |
string | yes | |
requirements.pools[].units |
integer | yes | min 1 |
requirements.quotas |
array of object | no | |
requirements.quotas[].name |
string | yes | |
requirements.quotas[].units |
integer | yes | min 1 |
requirements.budgets |
array of object | no | |
requirements.budgets[].name |
string | yes | |
requirements.budgets[].reserveMinor |
string | yes | pattern ^\d+$ |
workLimit |
string | no |
Responses
| Status | Meaning |
|---|---|
201 |
taskId |
409 |
Error envelope {"error":{"code","message","requestId"}} |
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks" \ -H "Authorization: Bearer $RUNSTATE_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"scopeId":"<run id>","mailboxId":"<mailboxId>","taskKey":"<taskKey>"}'GET /tasks/{id}
Section titled “GET /tasks/{id}”GET /v1/spaces/{spaceId}/tasks/{id}Restart-safe task view incl. outcome and subscribers.
- Key permission:
coordination_read - TypeScript SDK:
ticket.status(), ticket.result(), ticket.awaitAdmission() - Python SDK:
ticket.status(), ticket.result(), ticket.await_admission()
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
id |
string (uuid) | required |
Responses
| Status | Meaning |
|---|---|
200 |
Task view |
404 |
Error envelope {"error":{"code","message","requestId"}} |
curl -X GET "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks/<id>" \ -H "Authorization: Bearer $RUNSTATE_API_KEY"POST /tasks/{id}/cancel
Section titled “POST /tasks/{id}/cancel”POST /v1/spaces/{spaceId}/tasks/{id}/cancelCancel a nonterminal task and its delivery (cleanup, ungated)
- Key permission:
coordination_write - TypeScript SDK:
ticket.cancel() - Python SDK:
ticket.cancel()
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
id |
string (uuid) | required |
Request body (JSON)
| Field | Type | Required | Notes |
|---|---|---|---|
reason |
string | no | max length 512 |
Responses
| Status | Meaning |
|---|---|
200 |
CANCELLED |
409 |
Error envelope {"error":{"code","message","requestId"}} |
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks/<id>/cancel" \ -H "Authorization: Bearer $RUNSTATE_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{}'POST /tasks/{id}/join
Section titled “POST /tasks/{id}/join”POST /v1/spaces/{spaceId}/tasks/{id}/joinIdempotently subscribe to a shared task.
- Key permission:
coordination_write - TypeScript SDK:
ticket.join() - Python SDK:
ticket.join()
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
id |
string (uuid) | required |
Request body (JSON)
| Field | Type | Required | Notes |
|---|---|---|---|
subscriberId |
string | yes | |
scopeId |
string (uuid) | yes |
Responses
| Status | Meaning |
|---|---|
200 |
Task state |
404 |
Error envelope {"error":{"code","message","requestId"}} |
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks/<id>/join" \ -H "Authorization: Bearer $RUNSTATE_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"subscriberId":"<subscriberId>","scopeId":"<run id>"}'POST /tasks/{id}/detach
Section titled “POST /tasks/{id}/detach”POST /v1/spaces/{spaceId}/tasks/{id}/detachDetach a subscriber; zero subscribers does not cancel the task.
- Key permission:
coordination_write - TypeScript SDK:
ticket.detach() - Python SDK:
ticket.detach()
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
id |
string (uuid) | required |
Request body (JSON)
| Field | Type | Required | Notes |
|---|---|---|---|
subscriberId |
string | yes |
Responses
| Status | Meaning |
|---|---|
200 |
detached |
404 |
Error envelope {"error":{"code","message","requestId"}} |
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks/<id>/detach" \ -H "Authorization: Bearer $RUNSTATE_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"subscriberId":"<subscriberId>"}'GET /ops/tasks/{taskId}
Section titled “GET /ops/tasks/{taskId}”GET /v1/spaces/{spaceId}/ops/tasks/{taskId}Debugger task detail.
- Key permission:
usage_read
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
taskId |
string (uuid) | required |
Responses
| Status | Meaning |
|---|---|
200 |
Task view |
404 |
Error envelope {"error":{"code","message","requestId"}} |
curl -X GET "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/ops/tasks/<taskId>" \ -H "Authorization: Bearer $RUNSTATE_API_KEY"POST /tasks/admit
Section titled “POST /tasks/admit”POST /v1/spaces/{spaceId}/tasks/admitResource-aware admission; atomically claims a delivery plus declared resources.
Discovery picks READY deliveries FIFO; each candidate is re-checked under the documented multi-resource lock order. 204 when nothing can be admitted (after the waitMs long poll, if one was requested); an empty admit stores no response under its Idempotency-Key. The pool grants and work-limit slot are released with the delivery (complete, nack, or lease expiry) and renewed with it; quota consumptions are spent. Raw recv remains a bypass outside this guarantee.
- Key permission:
coordination_write - Idempotency-Key header: required
- TypeScript SDK:
mailbox.admit() - Python SDK:
mailbox.admit()
Path parameters
| Name | Type | Notes |
|---|---|---|
spaceId |
string (uuid) | required |
Request body (JSON)
| Field | Type | Required | Notes |
|---|---|---|---|
scopeId |
string (uuid) | yes | |
mailboxId |
string (uuid) | yes | |
holder |
string | yes | |
holderSession |
string | yes | |
leaseSeconds |
integer | no | default 30 |
waitMs |
integer | no | 0–120000; Long-poll an empty receive for up to this many milliseconds (capped by the server at api.longPollMaxWaitMs; 0 or absent answers at once). Returns as soon as work is available, when the wait ends, or when the API starts draining. An empty long poll of at least 1000 ms does not count toward request rate limits. |
Responses
| Status | Meaning |
|---|---|
200 |
Admitted delivery with token and claimed resources |
204 |
Nothing admissible right now |
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/tasks/admit" \ -H "Authorization: Bearer $RUNSTATE_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"scopeId":"<run id>","mailboxId":"<mailboxId>","holder":"worker-1","holderSession":"<session id>"}'