Skip to content
HomeConsoleGet started

Work done once per run, with the result stored for every caller.

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.

POST /v1/spaces/{spaceId}/once/acquire

Start once-per-run work, or learn its state.

ACQUIRED (201) hands this caller a fenced lease and token. DONE returns the stored result, FAILED the last error (lastError), HELD means another holder is working on it (wait with GET /once).

  • Key permission: coordination_write
  • TypeScript SDK: runstate.once(fn)
  • Python SDK: @runstate.once

Path parameters

Name Type Notes
spaceId string (uuid) required

Request body (JSON)

Field Type Required Notes
scopeId string (uuid) yes
key string yes length 1–512
holder string yes
holderSession string yes
leaseSeconds integer no 5–600; default 30

Responses

Status Meaning
200 HELD, DONE or FAILED
201 ACQUIRED: {state, token, generation, leaseExpiresAt, attempts}
409 Error envelope {"error":{"code","message","requestId"}}
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/once/acquire" \
-H "Authorization: Bearer $RUNSTATE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"scopeId":"<run id>","key":"<key>","holder":"worker-1","holderSession":"<session id>"}'
POST /v1/spaces/{spaceId}/once/renew

Extend the lease on once work.

  • Key permission: coordination_write
  • TypeScript SDK: runstate.once(fn) (automatic while fn runs)
  • Python SDK: @runstate.once (automatic while fn runs)

Path parameters

Name Type Notes
spaceId string (uuid) required

Request body (JSON)

Field Type Required Notes
scopeId string (uuid) yes
key string yes
token string yes
leaseSeconds integer no 5–600; default 30

Responses

Status Meaning
200 New lease expiry
409 Error envelope {"error":{"code","message","requestId"}}
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/once/renew" \
-H "Authorization: Bearer $RUNSTATE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"scopeId":"<run id>","key":"<key>","token":"<lease token>"}'
POST /v1/spaces/{spaceId}/once/complete

Store the result of once work (64 KiB max); allowed after the run stops.

  • Key permission: coordination_write
  • TypeScript SDK: runstate.once(fn)
  • Python SDK: @runstate.once

Path parameters

Name Type Notes
spaceId string (uuid) required

Request body (JSON)

Field Type Required Notes
scopeId string (uuid) yes
key string yes
token string yes
result any JSON no JSON result

Responses

Status Meaning
200 DONE
409 Error envelope {"error":{"code","message","requestId"}}
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/once/complete" \
-H "Authorization: Bearer $RUNSTATE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"scopeId":"<run id>","key":"<key>","token":"<lease token>"}'
POST /v1/spaces/{spaceId}/once/fail

Record a failed attempt; FAILED for everyone once maxAttempts is reached.

  • Key permission: coordination_write
  • TypeScript SDK: runstate.once(fn) (when fn throws)
  • Python SDK: @runstate.once (when fn raises)

Path parameters

Name Type Notes
spaceId string (uuid) required

Request body (JSON)

Field Type Required Notes
scopeId string (uuid) yes
key string yes
token string yes
error string yes max length 2000
maxAttempts integer no 1–100; default 3

Responses

Status Meaning
200 OPEN or FAILED, with attempts
409 Error envelope {"error":{"code","message","requestId"}}
curl -X POST "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/once/fail" \
-H "Authorization: Bearer $RUNSTATE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"scopeId":"<run id>","key":"<key>","token":"<lease token>","error":"<error>"}'
GET /v1/spaces/{spaceId}/once

Read once work; with waitMs, hold until it is no longer HELD.

  • Key permission: coordination_read
  • TypeScript SDK: runstate.once(fn) (waiting for another worker)
  • Python SDK: @runstate.once (waiting for another worker)

Path parameters

Name Type Notes
spaceId string (uuid) required

Query parameters

Name Type Notes
scopeId string (uuid)
key string
waitMs integer 0–120000

Responses

Status Meaning
200 {key, scopeId, state: OPEN|HELD|DONE|FAILED, generation, holder, leaseExpiresAt, attempts, result, lastError}
404 Error envelope {"error":{"code","message","requestId"}}
curl -X GET "$RUNSTATE_BASE_URL/v1/spaces/$RUNSTATE_SPACE_ID/once" \
-H "Authorization: Bearer $RUNSTATE_API_KEY"