Response envelope
Every v1 response — success or failure — shares one JSON shape. A successful call returns its resource under `data`; a failed call returns an `error` object carrying a canonical `code`, a human-readable `message`, and a `requestId` you can quote when asking for help.
{
"error": {
"code": "rate_limited",
"message": "Too many requests.",
"requestId": "req_...",
"retryAfterS": 4
}
}Canonical error codes
A few codes recur across every endpoint:
- `unauthorized` (401) — missing or invalid bearer token.
- `forbidden` (403) — the token's scopes don't cover this action.
- `wrong_region` (421) — retry against the `base_url` in the error payload; see Regions & base URLs.
- `rate_limited` (429) — back off for `retryAfterS` seconds before retrying.
- `not_found` (404) — the resource doesn't exist or isn't visible to this token's scopes.
Cursor pagination
List endpoints return a `nextCursor` field when more results are available. Pass it back as a `cursor` query parameter to fetch the next page — do not assume offset-based paging or a fixed page count.
Rate limits by plan
Rate limits apply per key and per organization, and scale with your plan's tier. Read-heavy calls (listing workflows, fetching runs) share a more generous bucket than mutating calls (creating or running a workflow); MCP tool calls have their own bucket. A 429 response always includes `retryAfterS`.