Errors, envelope & rate limits
The response envelope every v1 endpoint shares, canonical error codes, cursor pagination, and how rate limits scale with your plan.
Updates every sample URL on this page to your organization's regional host. Match the shard in your API key (wextl_<shard>_…).
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 and a human-readable message. Field names are snake_case on the wire (the TypeScript SDK renames a few to camelCase for you — see the SDK snippets).
{
"error": {
"code": "rate_limited",
"message": "Too many requests.",
"retry_after_s": 4
}
}{
"error": {
"code": "wrong_region",
"message": "This organization's data lives in a different region.",
"base_url": "https://eu1.wextl.com",
"region": "eu"
}
}Canonical error codes
Every error.code value a shipped v1 route or MCP tool can return, and what it means. Casing is deliberate and NOT uniform: a handful of public-surface-specific codes (rate_limited, wrong_region, workflow_active, workflow_not_deployed, workflow_modified) are lower_snake_case; everything else is UPPER_SNAKE_CASE. Match the exact string — unauthorized and UNAUTHENTICATED are not the same value.
UNAUTHENTICATED(401) — missing or invalid bearer token.FORBIDDEN(403) — the token's scopes don't cover this action — see the scope model in Authentication & scopes.PLAN_FEATURE_DISABLED(403) — the organization's plan doesn't include API access — returned on EVERY call until the org upgrades. The most common first-call failure.PLAN_LIMIT_EXCEEDED(403) — the organization has reached a plan-tier limit (e.g. active workflow count).PAYMENT_REQUIRED(402) — a payment is required before this organization can continue.ACTIVATION_REQUIRES_PLAN(402) — turning a workflow on needs an active plan — choose one in Billing, then retry.rate_limited(429) — back off forretry_after_sseconds before retrying — see Rate limits below.wrong_region(421) — retry against thebase_urlin the error payload; see Regions & base URLs.VALIDATION_ERROR(400) — the request body failed validation — seemessage(andfield/fieldswhen present) for detail.INVALID_JSON(400) — the request body was not valid JSON.PAYLOAD_TOO_LARGE(413) — the request body exceeded the size limit.NOT_FOUND(404) — the resource doesn't exist or isn't visible to this token's scopes.CONFLICT(409) — the request conflicts with the resource's current state — refresh and retry.workflow_active(409) — refuses to delete a currently-active workflow — deactivate it first.workflow_not_deployed(404) — requested?view=deployedon a workflow that has never been deployed.workflow_modified(409) — the workflow changed since theexpectedUpdatedAtyou sent was read — re-fetch and retry with the new value.CONCURRENCY_LIMIT(429) — the organization has reached its concurrent-run cap — wait for a run to finish before starting another.ORG_RELOCATING(503) — the organization's data is briefly unavailable while it relocates between regions — retry shortly.INTERNAL(500) — an unexpected server error.
Cursor pagination
List endpoints return a next_cursor field (the TypeScript SDK exposes this as nextCursor) 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. next_cursor is null on the last page.
Rate limits by plan
Rate limits are per-key AND per-organization (an org-wide bucket sums across every key/OAuth grant in the org, so splitting one integration across several keys never raises the effective ceiling), and scale with your plan's API rate tier. A 429 response always carries retry_after_s in the body and a matching Retry-After header.
Base per-key limits (tier starter, 1×) — multiplied by your plan's tier before enforcement:
read— 600/min. Discover/list/get/validate/resolve calls — the read-heavy majority of an agent's tool-call loop.mutation— 60/min. Graph verbs,create_workflow, schedule/active toggles, credentials, webhooks, databases DDL.mcp— 120/min. The/api/mcptools/call envelope — MCP is stateless one-call-per-request, andinitialize/tools/listcount against this too.run_start— 30/min. Starting a run specifically (start_runand REST run-start), isolated from the broadermutationbucket.envelope— 600/min. A per-key ceiling over ALL calls regardless of class — the backstop for/api/v1, which has no separate class-agnostic cap otherwise.- Org-aggregate — 3× the per-key ceiling above, summed across every key/grant in the organization.
starter 1× (base numbers above)
growth 2×
pro 4×
enterprise 8×References
- WEXTL® error envelope and rate-limit implementation.
- Our users' real error and retry patterns.
- The machine-readable OpenAPI error schema.