Error codes

Every error response has the shape {code, message, remediation, docs_url, request_id}. Include the request_id when reporting problems.

INVALID_REQUEST

The request body or parameters failed validation. The message lists the offending fields.

UNAUTHORIZED

Missing, malformed, expired, or revoked credential.

FORBIDDEN

The credential is valid but lacks the required scope.

AUTH_CHALLENGE_EXPIRED

The SIWE nonce is unknown, already used, or expired. Nonces are single-use.

AUTH_SIGNATURE_INVALID

Signature verification failed, or the SIWE message fields do not match this environment.

IDEMPOTENCY_CONFLICT

The Idempotency-Key was already used with a different payload.

NOT_FOUND

The resource does not exist or does not belong to this account.

RATE_LIMITED

Too many requests. Respect Retry-After; unauthenticated endpoints are limited per IP at the edge.

LIMIT_EXCEEDED

A prepaid balance top-up was refused because it would push a platform cap: your per-account prepaid balance, or the platform-wide aggregate prepaid float. The message names the cap in dollars. This is a limit on customer float the platform will hold, not a payment error — nothing was broadcast and no authorization was consumed. Top up a smaller amount, or spend down existing balance; the caps are operator-adjustable.

VENUE_UNAVAILABLE

No execution venue answered. Transient; retry shortly.

POLICY_VIOLATION

The request exceeds what the wallet's active policy authorizes. The message names the violated rule.

BUDGET_EXCEEDED

The spend would exceed a policy budget or velocity limit (see pre-flight POST /v1/checks).

COUNTERPARTY_BLOCKED

The counterparty is on a screening list (e.g. OFAC SDN) and the policy requires screening.

CONFLICT

The resource is in a state that forbids this transition (e.g. confirming a revoked delegation, or on-chain state moved since prepare). The message says which.

UNAVAILABLE

A required backend capability is not configured in this environment.

JURISDICTION_BLOCKED

Prediction-market surfaces are unavailable from this jurisdiction (venue-mirrored list; unknown origins are refused). Non-PM treasury features are unaffected.

EXECUTION_DISABLED

Delegated prediction-market order routing exists but is switched off in this environment. Pre-flight checks and reads remain available.

DEADLINE_EXCEEDED

The request spent its whole time budget waiting on third parties (venue APIs, RPC nodes) and stopped rather than wait longer. Returned as 504. Not the same as VENUE_UNAVAILABLE: a slow venue answered nothing wrong, and this was our scheduling decision, not theirs. The message says how much budget there was and what the handler refused to start; the remediation says whether anything was transmitted and names the read that confirms it. Nothing that moves funds is ever abandoned mid-flight — the budget is checked before a transaction is broadcast, never after, so a request that fails here either sent nothing or names the hashes it did send.

Intent abort reasons

When the executor stops an accepted intent, the intent's params.abort.reason and the intent.aborted event carry one of these codes. Partial results are never discarded: fills that settled are always ledgered before the abort.

UNSUPPORTED_KIND

The intent kind has no executor path yet. Delegated wallets also hit this when the delegation lives on the testbed chain, which has no venue — only gas top-ups (WETH unwrap) run there. POST /v1/delegations/prepare a grant on the execution chain to convert.

EXECUTOR_UNCONFIGURED

Signing credentials are not bound in this environment; nothing was signed. This is an operator-side gap, not a request the caller can fix — retrying will fail identically until the environment is bound.

NO_DELEGATION

The wallet has no active session-key delegation. POST /v1/delegations/prepare, then POST /v1/delegations/{id}/confirm the grant it returns.

UNSUPPORTED_CHAIN

The pinned policy targets a chain this execution path does not serve (venues are mainnet-only; delegations run where granted). GET /v1/tokens lists the chains that are served; PUT /v1/policies to repin this wallet to one of them.

POLICY_VIOLATION

Re-checked at the moment of execution and refused; the detail names the violated rule. Two different things land here and the detail distinguishes them: a rule in the wallet's own policy, which PUT /v1/policies changes, or 'outside the delegated scope', which means the on-chain grant does not authorize the call — a narrower gate the policy cannot widen. Re-grant with POST /v1/delegations/prepare for the latter.

INSUFFICIENT_BALANCE

The wallet does not hold, on-chain, the TOKENS the intent sells. This is the wallet's own chain balance and NOT the prepaid fee balance that pays for API calls — that one refuses with a 402 or BUDGET_EXCEEDED and is refilled with POST /v1/balance/topup. Topping up fees does nothing for this abort, and vice versa. On a conversion: earlier partial fills or an outside transfer drained the position below the requested size, so re-read the wallet and submit a smaller POST /v1/intents. On a gas_topup: the wallet holds no wrapped native (WETH) to unwrap, so the automatic top-up that keeps it able to transact has nothing to work with — convert something the wallet DOES hold into WETH with POST /v1/intents, or send native funds to the wallet directly. The detail names the token, the balance held and the amount required.

DEPTH_COLLAPSE

Live venue depth cannot support even two slices at the requested size. POST /v1/quotes to see what size the venues will actually price right now, then POST /v1/intents for that smaller size — this is a size problem, and retrying the same size will refuse identically.

PRICE_GAP

Venue price diverged from the independent reference beyond twice the slippage budget. POST /v1/quotes to see the current spread; retry when it narrows, or PUT /v1/policies to widen execution.max_slippage_bps if the wallet genuinely accepts that price.

VENUE_DISAGREEMENT

The venue's own quotes imply inconsistent pricing beyond ten times the slippage budget. POST /v1/quotes to observe the pair before resubmitting; this usually clears on its own within minutes and widening slippage is NOT the fix — the quotes are internally inconsistent, not merely wide.

VENUE_NO_QUOTE

A venue could not price this pair at all — most often the pair is not routable there. Distinct from VENUE_DISAGREEMENT, where venues answered and their prices conflicted. GET /v1/tokens for the tradeable set and POST /v1/quotes to test the pair before committing an intent.

UNSUPPORTED_TOKEN

One of the tokens is not in this chain's registry, so its decimals and stable-ness are unknown and it cannot be sized or priced safely. Use a supported token; GET /v1/tokens lists every token this platform accepts, per chain.

VENUE_UNAVAILABLE

No venue could even be asked: none supports the chain, none survived the policy's execution.venues allowlist, or an operator has switched the last one off. The detail names each venue and its state. Distinct from VENUE_NO_QUOTE, where a venue was asked and declined to price. Read the detail before retrying: an allowlist that names no serving venue is a policy the caller fixes with PUT /v1/policies, while an operator switch-off is an outage that only time fixes.

NO_PRICE_REFERENCE

Only one venue can fill AND no independent price reference (an on-chain oracle feed) covers this pair, so the price cross-check has nothing to compare against. Single-venue execution normally continues against an oracle reference; this is the one case that still refuses, because filling on a single unverified quote is worse than not filling. Not a retry: route through a pair that has a reference — GET /v1/tokens names the stables, and a leg through one of them is covered.

SPEND_CAP_EXCEEDED

The wallet's own policy.spend caps refuse this conversion. The detail names which cap (spend.per_tx_usd, spend.daily_usd or spend.velocity_per_hour) and by how much. This is the mandate working rather than an outage: daily_usd refills at UTC midnight and velocity_per_hour within the hour, so back off and POST /v1/intents again later, or PUT /v1/policies to raise the cap if the wallet's mandate genuinely allows it. Also raised when neither leg of the pair is a USD stable, because the caps then have no notional to evaluate against — route through the float token instead.

FEE_UNFUNDED

The prepaid FEE balance was drained by a concurrent request between this intent's admission and its fee debit, so it was terminally aborted before any execution — nothing was signed, nothing moved, and no fee was charged. This IS the prepaid balance that pays for API calls (the companion of the 402), not the wallet's on-chain funds. POST /v1/balance/topup, then resubmit POST /v1/intents.

EXECUTION_FAILED

A slice failed on-chain after zero or more recorded fills; everything that settled is ledgered. GET /v1/intents/{id} for the fills that landed, then POST /v1/intents for the remainder if you still want it — this intent is terminal and will not resume.

EXECUTION_ERROR

An unexpected error stopped execution; recorded fills were persisted before the abort. GET /v1/intents/{id} for what settled before resubmitting, so the remainder is sized against what actually landed rather than against the original request.

EXECUTION_INTERRUPTED

The run stopped with work left: it ran out of the continuations it is allowed, the policy's execution.deadline_minutes elapsed first, or a broadcast transaction could not be confirmed before the executor had to hand off. NOT an outage and NOT a failed trade — nothing is known to have gone wrong, only to be unresolved, and some of the intent very likely filled. GET /v1/intents/{id} FIRST: the fills that settled are journaled there, and the detail names any transaction hash that was broadcast without a confirmed receipt (that one may still mine after this abort). Size any POST /v1/intents for the remainder against what actually landed; resubmitting the original size double-trades the part that already filled.