# Error codes

Every public Polyester error code, with its numeric value, HTTP status, Connect code, and meaning.

Branch on the error code, never on the message text. Each entry names a code as REST returns it in the problem+json `code` field. ConnectRPC returns the same code in the error detail, as a value of the enum named in each section; where a section names a prefix, the protobuf enum name starts with it. The number after each code is its enum value. Order codes use the same numbers on the SBE and Protobuf trade WebSockets.

Each entry gives the code, its enum value, the REST HTTP status, then the ConnectRPC code. Where an entry lists more than one value, the code is returned with each of them depending on the operation. How errors are shaped on each interface, and which ones are safe to retry, is on [Error responses](https://testnet.polyester.com/docs/developer-docs/error-handling/error-responses). The [API reference](https://testnet.polyester.com/docs/api-docs) lists the errors of each operation.

## Orders and triggers

Enum `orders.v1.ErrorCode`, prefix `ERROR_CODE_`. Order entry, modification, cancellation, triggers, TWAP and ladder orders, and order and trade reads. The SBE and Protobuf trade WebSockets use the same numbers.

### Outcome unknown

- **`TRIGGER_CONTROL_OUTCOME_UNKNOWN`** · 253 · HTTP 504 · `deadline_exceeded`\
  The trigger change was not confirmed within its time bound. Its outcome is unknown and it may still apply; read the trigger before retrying.
- **`ORDER_CANCEL_OUTCOME_UNKNOWN`** · 297 · HTTP 504 · `deadline_exceeded`\
  The order cancellation was sent but not confirmed in time. Its outcome is unknown and it may still apply; read the order before retrying. For a batch cancellation, every item's outcome is unknown; read them back. For a cancel all, some or all of the matching orders may be canceled; read open orders. For a cancel all after heartbeat, the switch may or may not have been armed, refreshed or disabled; send the heartbeat again.
- **`ORDER_MODIFY_OUTCOME_UNKNOWN`** · 298 · HTTP 504 · `deadline_exceeded`\
  The order modification was sent but not confirmed in time. Its outcome is unknown and it may still apply; read the order before retrying. For a batch replacement, every item's outcome is unknown; read them back.
- **`ORDER_CREATE_OUTCOME_UNKNOWN`** · 303 · HTTP 504 · `deadline_exceeded`\
  The order was sent but not confirmed in time. Its outcome is unknown and it may have been accepted; read the order by its client order ID, or read open orders, before retrying. For a batch create, every item's outcome is unknown; read them back, or repeat the batch with the same request ID and payload within 15 minutes, which returns decided items' original results and retries the rest without admitting any item twice.
- **`TRIGGER_CREATE_OUTCOME_UNKNOWN`** · 304 · HTTP 504 · `deadline_exceeded`\
  The trigger was sent but not confirmed in time. Its outcome is unknown and it may have been created; read the triggers for its client trigger ID before retrying.

### Request and encoding

- **`BAD_REQUEST`** · 1 · HTTP 400 · `invalid_argument`\
  Request could not be parsed or was structurally invalid.
- **`INVALID_ARGUMENT`** · 2 · HTTP 400 · `invalid_argument`\
  Request fields failed validation.
- **`BATCH_TOO_LARGE`** · 33 · HTTP 400 · `invalid_argument`\
  Batch size exceeds the maximum allowed.
- **`VALIDATION_ERROR`** · 66 · HTTP 400 · `invalid_argument`\
  Request failed structural or cross-field validation.
- **`INVALID_ORDER_ID`** · 80 · HTTP 400 · `invalid_argument`\
  The order identifier or the replacement order identifier is not valid.
- **`INVALID_SIDE`** · 211 · HTTP 400 · `invalid_argument`\
  The order side, or a trigger's child order side, is not a known side.
- **`INVALID_ORDER_TYPE`** · 212 · HTTP 400 · `invalid_argument`\
  The order type, or a trigger's child order type, is not a known order type.
- **`INVALID_STP_MODE`** · 213 · HTTP 400 · `invalid_argument`\
  The self-trade prevention mode is not a known mode.
- **`INVALID_ORDER_FLAGS`** · 214 · HTTP 400 · `invalid_argument`\
  An order flag is unknown, or not accepted with this order type or time in force, or on a trigger's child order.
- **`BATCH_OTHER_ITEM_INVALID`** · 215 · HTTP 400 · `invalid_argument`\
  Another item of the same batch was invalid, so this item was not applied either. Nothing in the batch changed.
- **`REPLACE_ONTO_OWN_ID`** · 216 · HTTP 400 · `invalid_argument`\
  The replacement order identifier equals the identifier of the order it replaces.
- **`INVALID_CLIENT_ORDER_ID`** · 217 · HTTP 400 · `invalid_argument`\
  The client order ID is longer than 36 bytes or otherwise not valid.
- **`INVALID_HANDLING_MODE`** · 219 · HTTP 400 · `invalid_argument`\
  The order handling mode is not a known or accepted mode.
- **`CANCEL_ALL_AFTER_TIMEOUT_INVALID`** · 222 · HTTP 400 · `invalid_argument`\
  The cancel-all-after timeout is neither 0, which disarms it, nor between 10 and 120 seconds.
- **`CANCEL_SCOPE_TOO_LARGE`** · 223 · HTTP 400 · `invalid_argument`\
  The cancel-all request named more than 100 symbols.
- **`INVALID_MODIFY_BEHAVIOR`** · 228 · HTTP 400 · `invalid_argument`\
  The modify behavior is not a known behavior.
- **`BATCH_REPLACE_ONLY_REQUIRED`** · 229 · HTTP 400 · `invalid_argument`\
  No longer returned: each BatchReplaceOrders item follows ModifyOrder's default amend-or-replace rule. The value stays reserved.
- **`BATCH_SINGLE_SYMBOL_REQUIRED`** · 230 · HTTP 400 · `invalid_argument`\
  An item of the batch modify named no symbol, or another symbol than the batch's first item, so the batch was refused.
- **`INTENT_ID_INVALID`** · 232 · HTTP 400 · `invalid_argument`\
  The cancel-all or cancel-all-after request carried an intent identifier of zero.
- **`DRY_RUN_INVALID`** · 233 · HTTP 400 · `invalid_argument`\
  The cancel-all request's dry-run flag was neither 0 nor 1.

### Order parameters

- **`BAD_PRICE`** · 5 · HTTP 400 · `invalid_argument`\
  Price is invalid for the requested order.
- **`BAD_QTY`** · 6 · HTTP 400 · `invalid_argument`\
  Quantity is invalid for the requested order.
- **`MIN_NOTIONAL`** · 7 · HTTP 400 · `invalid_argument`\
  Order notional is below the pair minimum.
- **`QTY_STEP_SIZE`** · 8 · HTTP 400 · `invalid_argument`\
  Quantity does not align with the pair step size.
- **`FEE_ASSET_NOT_ALLOWED`** · 15 · HTTP 400 · `invalid_argument`\
  Requested fee asset is not allowed for this order.
- **`PRICE_TICK_SIZE`** · 30 · HTTP 400 · `invalid_argument`\
  Price must align with the pair tick size, including trigger and activation prices.
- **`MIN_QTY`** · 31 · HTTP 400 · `invalid_argument`\
  Quantity is below the pair minimum quantity (base units).
- **`POST_ONLY_LIMIT_ONLY`** · 32 · HTTP 400 · `invalid_argument`\
  Post-only is only valid for LIMIT orders.
- **`MAX_SLIPPAGE_INVALID`** · 48 · HTTP 400 · `invalid_argument`\
  Max slippage (ticks or bps) is out of range or leaves no valid execution price bound. Applies to market orders and to standalone and attached trailing stops, on create and on modify; for example, a 10000 bps cap on a market order or trailing stop that sells.
- **`MAX_QUOTE_DEBIT_TOO_SMALL`** · 68 · HTTP 400 · `invalid_argument`\
  The all-in quote budget cannot resolve one valid step-aligned base quantity.
- **`MAX_QTY`** · 74 · HTTP 400 · `invalid_argument`\
  Quantity is above the pair maximum: the market-order maximum for MARKET orders, the limit-order maximum otherwise (base units).
- **`MAX_NOTIONAL`** · 75 · HTTP 400 · `invalid_argument`\
  Order notional is above the pair maximum (quote units). A stricter sub-account policy cap returns `POLICY_MAX_NOTIONAL` instead.
- **`PRICE_LEVEL_QUANTITY_LIMIT`** · 127 · HTTP 400 · `failed_precondition`\
  The order would take the total quantity resting at its price past the most a price level can hold, even if some quantity still fits. Nothing changed: a new order was not placed, a modified order keeps resting as it was, and the other orders at that price are unchanged. Another price or a smaller quantity, or the same order once less quantity rests at that price, is accepted.
- **`INVALID_TIME_IN_FORCE`** · 202 · HTTP 400 · `invalid_argument`\
  The time in force, or its expiry time, is not accepted for this order or for a trigger's child order type.
- **`STP_MODE_NOT_ALLOWED`** · 206 · HTTP 400 · `invalid_argument`\
  The self-trade prevention mode is not one the venue accepts for this order.

### Funds and account limits

- **`INSUFFICIENT_FUNDS`** · 3 · HTTP 400 · `invalid_argument`\
  Account does not have enough available balance for the order.
- **`POLICY_MAX_NOTIONAL`** · 21 · HTTP 400 · `invalid_argument`\
  Sub-account policy max order notional exceeded.
- **`POLICY_MAX_OPEN_ORDERS`** · 34 · HTTP 400 · `invalid_argument`\
  Sub-account policy maximum number of open orders has been reached.
- **`RISK_LIMIT`** · 55 · HTTP 400 · `invalid_argument`\
  Account-level risk limits were exceeded.
- **`SETTLEMENT_BACKLOGGED`** · 84 · HTTP 503 · `unavailable`\
  The account has too many filled or ended orders whose settlement has not completed yet. Nothing changed; the request is accepted again once settlement catches up.
- **`MAX_OPEN_ORDERS_TOTAL`** · 205 · HTTP 400 · `invalid_argument`\
  The account has reached its maximum number of open orders across all markets. A stricter sub-account policy cap returns `POLICY_MAX_OPEN_ORDERS` instead.
- **`ACCOUNT_RESERVATION_LIMIT_REACHED`** · 257 · HTTP 429 · `resource_exhausted`\
  The account's open orders and triggers hold its maximum number of fund reservations.
- **`ACCOUNT_ORDERS_SUSPENDED`** · 263 · HTTP 400 · `failed_precondition`\
  New orders, changes and trigger orders on this account are suspended until a balance issue is resolved; cancels still work. Nothing changed.
- **`ORDER_REPAIRING`** · 299 · HTTP 400 · `failed_precondition`\
  This order is being canceled while the account's balances are brought back in line, so it can't be changed. Nothing changed; cancels still work, and the account's other orders can still be changed.
- **`ACCOUNT_REPAIRING`** · 300 · HTTP 400 · `failed_precondition`\
  This account's orders are being canceled while its balances are brought back in line, so new orders, changes and trigger orders are paused for a short time. Nothing changed; cancels still work. Try again shortly.
- **`MAX_OPEN_ORDERS_PER_PAIR`** · 306 · HTTP 400 · `invalid_argument`\
  The account has reached its maximum number of resting orders in this market. Good-till-cancelled and good-till-date orders count until they end; immediate-or-cancel, fill-or-kill and market orders never count, and a replace keeps its order's place. Nothing changed; cancel a resting order in this market first.

### Market state and pricing

- **`UNKNOWN_SYMBOL`** · 4 · HTTP 400 · `invalid_argument`\
  Requested trading symbol is unknown.
- **`PAIR_DISABLED`** · 16 · HTTP 400 · `invalid_argument`\
  Pair is disabled and does not accept orders.
- **`MARKET_PRICE_UNAVAILABLE`** · 37 · HTTP 400 · `failed_precondition`\
  MARKET BUY cannot be reserved because no reference/top-of-book price is available.
- **`PAIR_NOT_LISTED_YET`** · 50 · HTTP 400 · `invalid_argument`\
  Pair exists but is not listed yet.
- **`PAIR_DELISTED`** · 51 · HTTP 400 · `invalid_argument`\
  Pair was delisted and is no longer tradable.
- **`PAIR_CANCEL_ONLY`** · 52 · HTTP 400 · `invalid_argument`\
  Pair is in cancel-only mode.
- **`PAIR_POST_ONLY`** · 53 · HTTP 400 · `invalid_argument`\
  Pair is in post-only mode and requires `post_only=true`.
- **`PAIR_REDUCE_ONLY`** · 54 · HTTP 400 · `invalid_argument`\
  Pair is in reduce-only mode and does not accept new spot orders.
- **`MARKET_HALTED`** · 56 · HTTP 400 · `invalid_argument`\
  Market is halted.
- **`POST_ONLY_CROSS`** · 58 · HTTP 400 · `invalid_argument`\
  Post-only order would cross the book.
- **`REDUCE_ONLY_BLOCKED`** · 59 · HTTP 400 · `invalid_argument`\
  Reduce-only policy blocked the order.
- **`PRICE_BAND_VIOLATION`** · 60 · HTTP 400 · `invalid_argument`\
  Price band guard rejected the order.
- **`MARKET_CAP_VIOLATION`** · 61 · HTTP 400 · `invalid_argument`\
  Market-cap guard rejected the order.
- **`EMPTY_BOOK`** · 62 · HTTP 400 · `invalid_argument`\
  Market order could not execute due to empty book.
- **`FOK_INSUFFICIENT_LIQUIDITY`** · 63 · HTTP 400 · `invalid_argument`\
  FOK order rejected due to insufficient immediate liquidity.
- **`STALE_QUOTE`** · 65 · HTTP 400 · `failed_precondition`\
  Client reference price is stale compared to server-side BBO/drift policy.
- **`MARKET_QUOTE_STALE`** · 200 · HTTP 400 · `failed_precondition`\
  The market order carried no client reference price, and the pair's reference quote (top of book) was older than its freshness bound when the order was admitted.
- **`MARKET_QUOTE_UNHEALTHY`** · 201 · HTTP 400 · `failed_precondition`\
  The market order carried no client reference price, and the pair's reference quote could not be used to price it, for example because it postdated the order or carried an invalid price.
- **`ORDER_LIMITS_UNAVAILABLE`** · 273 · HTTP 400 · `failed_precondition`\
  This market's order limits aren't set yet, so it can't take new orders.
- **`ORDER_TYPE_NOT_ALLOWED_IN_AUCTION`** · 274 · HTTP 400 · `failed_precondition`\
  This market is in an auction call and takes only limit orders that rest without crossing the book; market, immediate-or-cancel and fill-or-kill orders are refused. Nothing changed.
- **`POST_ONLY_NOT_ALLOWED_IN_AUCTION`** · 275 · HTTP 400 · `failed_precondition`\
  This market is in an auction call; new post-only orders are refused. Nothing changed.
- **`SELF_TRADE_PREVENTED`** · 307 · HTTP 400 · `failed_precondition`\
  Self-trade prevention expired the order of an attached take-profit, stop-loss or trailing stop because it would have traded with another of the account's resting orders. It is reported as the trigger's fire refusal reason, never as the answer to a request: the attached order stays active. New trades and price updates do not fire it while the other order is first in line at the best price; once that order is gone or no longer first there, it fires again if its trigger condition still holds.

### Authentication and permissions

- **`UNAUTHENTICATED`** · 11 · HTTP 401 · `unauthenticated`\
  Caller is not authenticated.
- **`PERMISSION_DENIED`** · 12 · HTTP 403 · `permission_denied`\
  Caller is authenticated but not allowed to perform this action.
- **`SUBACCOUNT_INACTIVE`** · 19 · HTTP 400 · `failed_precondition`\
  Sub-account is present but not in an active state (disabled, deleted, etc.).
- **`POLICY_MARKET_DENY`** · 20 · HTTP 403 · `permission_denied`\
  Sub-account policy prevented trading on this market (e.g. pair mask).
- **`POLICY_TRADING_HALTED`** · 22 · HTTP 403 · `permission_denied`\
  Trading has been globally halted for this sub-account.
- **`POLICY_SPOT_TRADE_DENY`** · 23 · HTTP 403 · `permission_denied`\
  Sub-account policy does not allow spot trading (action mask).
- **`API_KEY_ROOT_SCOPE_ONLY`** · 24 · HTTP 403 · `permission_denied`\
  API key is scoped to the master/root account and cannot trade on sub-accounts.
- **`API_KEY_SUB_SCOPE_ONLY`** · 25 · HTTP 403 · `permission_denied`\
  API key is scoped to a specific sub-account and cannot trade on the master/root account.
- **`API_KEY_SUBACCOUNT_MISMATCH`** · 26 · HTTP 403 · `permission_denied`\
  API key is scoped to a different sub-account than the one requested.
- **`API_KEY_POLICY_REQUIRED`** · 27 · HTTP 403 · `permission_denied`\
  API key must have an attached policy before it can be used for trading.
- **`API_KEY_UNKNOWN`** · 28 · HTTP 403 · `permission_denied`\
  API key referenced in the request could not be resolved by the Orders service.
- **`API_KEY_MARKET_DENY`** · 29 · HTTP 403 · `permission_denied`\
  API key policy does not allow trading this market, even though the sub-account policy does.
- **`ACCOUNT_UNKNOWN`** · 57 · HTTP 400 · `invalid_argument`\
  Referenced account could not be resolved by the trading service.
- **`SUBACCOUNT_READ_FORBIDDEN`** · 70 · HTTP 403 · `permission_denied`\
  Caller has a sub-account role that does not allow reading spot data.
- **`POLICY_SPOT_READ_DENY`** · 71 · HTTP 403 · `permission_denied`\
  Sub-account policy does not allow reading spot data.
- **`API_KEY_SPOT_READ_DENY`** · 72 · HTTP 403 · `permission_denied`\
  API key policy does not allow reading spot data.

### Order identity and state

- **`CONFLICT_DUPLICATE_CLIENT_ORDER_ID`** · 9 · HTTP 409 · `already_exists`\
  Client order ID is already in use on this account, by an open order or by an order that ended recently; an ended order keeps its client order ID reserved for at least 60 seconds. Reuse returns this code even with the same payload. Use GetOrder to reconcile, then retry with a new client order ID.
- **`NOT_FOUND`** · 13 · HTTP 404 · `not_found`\
  Requested order or resource was not found.
- **`ORDER_UNKNOWN`** · 17 · HTTP 404 · `not_found`\
  Referenced order could not be resolved.
- **`MODIFICATION_REQUIRES_REPLACE`** · 35 · HTTP 400 · `invalid_argument`\
  Modify request in `AMEND_ONLY` mode requires replace semantics.
- **`CONFLICT_IDEMPOTENCY_KEY_REUSE`** · 36 · HTTP 409 · `already_exists`\
  Idempotency key was reused with a different payload.
- **`ORDER_ALREADY_TERMINAL`** · 64 · HTTP 400 · `failed_precondition`\
  The order has already ended (filled, canceled or expired).
- **`CANCEL_REQUEST_EXPIRED`** · 73 · HTTP 400 · `failed_precondition`\
  The cancel request exceeded its bounded internal replay window.
- **`QTY_AT_OR_BELOW_FILLED`** · 76 · HTTP 400 · `failed_precondition`\
  The replacement total quantity is at or below the order's filled quantity: the order ended at its filled quantity and no replacement order was created.
- **`DUPLICATE_ORDER_ID`** · 204 · HTTP 409 · `already_exists`\
  The order identifier assigned to the request is already in use by another order of the market. Nothing changed.
- **`ORDER_ID_CONFLICT`** · 210 · HTTP 409 · `already_exists`\
  The order identifier is held by a different, earlier order, so the request was not applied. Nothing changed.
- **`ORDER_MODIFY_IN_PROGRESS`** · 226 · HTTP 503 · `unavailable`\
  An earlier amend or replace of the order has not completed yet. Retry once it completes.
- **`ORDER_PLACEMENT_PENDING`** · 227 · HTTP 503 · `unavailable`\
  The order, or the replace that created it, has not been placed on the book yet, so it cannot be modified. Retry shortly.
- **`CANCEL_ALL_AFTER_SCOPE_CONFLICT`** · 234 · HTTP 400 · `failed_precondition`\
  A cancel-all-after is already due to fire, and the re-arm's scope does not cover every symbol of the pending one.

### Triggers, TWAP, ladders, and attached legs

- **`TRIGGER_PRICE_INVALID`** · 40 · HTTP 400 · `invalid_argument`\
  Trigger price is invalid (e.g., TP below current price for long).
- **`TRIGGER_PRICE_SOURCE_UNSUPPORTED`** · 41 · HTTP 400 · `invalid_argument`\
  Trigger price source not supported (e.g., `INDEX_PRICE` before it's available).
- **`TRAILING_DISTANCE_INVALID`** · 42 · HTTP 400 · `invalid_argument`\
  Trailing stop distance must be positive.
- **`TRIGGER_NOT_FOUND`** · 43 · HTTP 404 · `not_found`\
  Trigger not found (for cancel/get operations).
- **`TRIGGER_STATUS_INVALID`** · 45 · HTTP 400 · `invalid_argument`\
  Trigger status does not allow requested lifecycle operation.
- **`TRIGGER_NOT_MODIFIABLE`** · 46 · HTTP 400 · `invalid_argument`\
  Trigger type/state does not support requested lifecycle operation.
- **`CONFLICT_DUPLICATE_CLIENT_TRIGGER_ID`** · 47 · HTTP 409 · `already_exists`\
  Client trigger ID is already used, either by a trigger with a different payload or by an earlier create that failed or was rolled back. List triggers to reconcile by client trigger ID, then retry with a new client trigger ID.
- **`CHILD_QTY_RAISE_NOT_ALLOWED`** · 81 · HTTP 400 · `invalid_argument`\
  The quantity of a trigger's child order or a ladder order can't be raised above its planned quantity. Nothing changed.
- **`ATTACHED_RISK_NOT_SUPPORTED`** · 82 · HTTP 501 · `unimplemented`\
  Attached take-profit, stop-loss or trailing legs can't be applied here: this market takes none, an attached trailing stop isn't offered yet, or the modify changes them together with the order's price, quantity, client order ID or a replace. Nothing changed.
- **`ATTACHED_LEGS_EXCEEDED`** · 86 · HTTP 400 · `invalid_argument`\
  The order already carries every attached leg it may hold, so another attached leg was refused. Legs being cancelled count until they end: retry once they have ended.
- **`FEE_ASSET_INVALID`** · 87 · HTTP 400 · `invalid_argument`\
  The trigger's fee asset was not valid.
- **`FEE_CEILING_INVALID`** · 88 · HTTP 400 · `invalid_argument`\
  The trigger's maximum fee rate was not valid.
- **`UNSUPPORTED_FIELD_SET`** · 89 · HTTP 400 · `invalid_argument`\
  The trigger set a field that must be left unset.
- **`TRIGGER_FIRE_LIMIT_REACHED`** · 90 · HTTP 429 · `resource_exhausted`\
  The trigger could not fire again.
- **`CONDITION_FLAGS_INVALID`** · 91 · HTTP 400 · `invalid_argument`\
  The trigger's condition flags were not valid.
- **`CONDITION_PARAMETER_SET`** · 92 · HTTP 400 · `invalid_argument`\
  The trigger set a condition parameter its condition does not take.
- **`TWAP_CAPACITY_REACHED`** · 93 · HTTP 429 · `resource_exhausted`\
  The market had no room for another TWAP order.
- **`CHILD_ORDER_INCONSISTENT`** · 94 · HTTP 400 · `failed_precondition`\
  The trigger's child order did not match the order the trigger requested, so the trigger failed and the child order was canceled.
- **`TRIGGER_CHILD_PRICE_NOT_MODIFIABLE`** · 236 · HTTP 400 · `invalid_argument`\
  The modify patched the trigger's child limit price or price mode, which the trigger does not accept.
- **`TRIGGER_GENERATIONS_EXHAUSTED`** · 237 · HTTP 400 · `failed_precondition`\
  The trigger reached its last modification. Nothing changed; cancel it and create a new trigger instead.
- **`TRIGGER_CONTROL_SHARE_EXHAUSTED`** · 238 · HTTP 429 · `resource_exhausted`\
  The account has its maximum number of trigger changes whose outcome is still pending. Retry shortly.
- **`TRIGGER_CONTROLS_BUSY`** · 239 · HTTP 503 · `unavailable`\
  The venue's capacity for pending trigger changes is exhausted across accounts. Retry shortly.
- **`TRIGGER_TYPE_NOT_SUPPORTED`** · 240 · HTTP 400 · `invalid_argument`\
  The trigger type is valid but not supported on this venue yet.
- **`INVALID_TRIGGER_TYPE`** · 241 · HTTP 400 · `invalid_argument`\
  The trigger type is not a known type.
- **`TRIGGER_DIRECTION_INVALID`** · 242 · HTTP 400 · `invalid_argument`\
  The trigger direction is neither ABOVE nor BELOW.
- **`TRIGGER_QTY_INVALID`** · 243 · HTTP 400 · `invalid_argument`\
  The trigger's child order quantity is not positive.
- **`TRIGGER_BUY_REQUIRES_LIMIT`** · 244 · HTTP 400 · `invalid_argument`\
  A buy trailing stop's child order is not a LIMIT order with a maximum price; its funds are reserved at that price.
- **`ACCOUNT_ROUTING_INVALID`** · 245 · HTTP 503 · `unavailable`\
  The account's trading route is not configured for triggers, so the trigger was not admitted. Contact support if it persists.
- **`TRIGGER_LIMIT_EXCEEDED`** · 246 · HTTP 429 · `resource_exhausted`\
  The account has its maximum number of live and recently ended triggers.
- **`TRIGGER_CONTROL_IN_PROGRESS`** · 247 · HTTP 503 · `unavailable`\
  An earlier change of the trigger has not completed yet. Retry once it completes.
- **`TRIGGER_PATCH_EMPTY`** · 248 · HTTP 400 · `invalid_argument`\
  The trigger modify named no field to change.
- **`CLIENT_TRIGGER_ID_INVALID`** · 249 · HTTP 400 · `invalid_argument`\
  The client trigger ID is empty, longer than 36 bytes or otherwise not valid.
- **`TRIGGER_ACTIVATION_PRICE_INVALID`** · 250 · HTTP 400 · `invalid_argument`\
  The trailing trigger's activation price is not positive or not on the pair's tick.
- **`SLIPPAGE_TICKS_INVALID`** · 251 · HTTP 400 · `invalid_argument`\
  The trigger's slippage bound in ticks is not valid for its child order.
- **`SLIPPAGE_BPS_INVALID`** · 252 · HTTP 400 · `invalid_argument`\
  The trigger's slippage bound in basis points is not valid for its child order.
- **`TRIGGER_CAPACITY_REACHED`** · 254 · HTTP 429 · `resource_exhausted`\
  The venue holds its maximum number of triggers across accounts right now. Retry later.
- **`RESERVATION_CAPACITY_REACHED`** · 255 · HTTP 429 · `resource_exhausted`\
  The venue's capacity for fund reservations is exhausted right now, so the trigger's child order could not be reserved. Retry later.
- **`CLIENT_ORDER_ID_CAPACITY_REACHED`** · 256 · HTTP 429 · `resource_exhausted`\
  The venue's capacity for reserved client order IDs is exhausted right now, so the trigger's child order could not reserve one. Retry later.
- **`INVALID_TRIGGER_CONTROL`** · 258 · HTTP 400 · `invalid_argument`\
  The requested trigger operation is not a known operation.
- **`TRIGGER_PATCH_NOT_ALLOWED`** · 259 · HTTP 400 · `invalid_argument`\
  A trigger operation other than modify carried field changes.
- **`TRIGGER_PATCH_FIELD_UNKNOWN`** · 260 · HTTP 400 · `invalid_argument`\
  The trigger modify named a field that is not known.
- **`TRIGGER_PATCH_VALUE_UNMASKED`** · 261 · HTTP 400 · `invalid_argument`\
  The trigger modify carried a value for a field its change mask does not name.
- **`TRIGGER_PATCH_PRICE_MODE_INVALID`** · 262 · HTTP 400 · `invalid_argument`\
  The trigger modify's price mode is not a known mode.
- **`TRAILING_SIDE_NOT_SUPPORTED`** · 264 · HTTP 400 · `invalid_argument`\
  A trailing stop's side is not supported. Trailing stops accept either side, so this code is not currently returned.
- **`TRAILING_CHILD_NOT_MARKET`** · 265 · HTTP 400 · `invalid_argument`\
  A trailing stop that sells must have a MARKET child order.
- **`TWAP_DURATION_INVALID`** · 266 · HTTP 400 · `invalid_argument`\
  The TWAP duration is shorter than 1 second or longer than about 292 years, the longest the venue's clock represents.
- **`LIMIT_CHILD_SLIPPAGE_SET`** · 267 · HTTP 400 · `invalid_argument`\
  The TWAP sets a slippage bound, but its slices are LIMIT orders, which take none.
- **`SLIPPAGE_BOUNDS_CONFLICT`** · 268 · HTTP 400 · `invalid_argument`\
  The slippage bound is given both in ticks and in basis points; give only one.
- **`TWAP_INTERVAL_INVALID`** · 269 · HTTP 400 · `invalid_argument`\
  The TWAP slice interval is shorter than 100 milliseconds or longer than its duration.
- **`LADDER_LEVEL_REJECTED`** · 270 · HTTP 400 · `invalid_argument`\
  One of the ladder's orders can't be placed, so the ladder was not created. Nothing changed.
- **`LADDER_RANGE_TOO_NARROW`** · 271 · HTTP 400 · `invalid_argument`\
  The ladder's price range is too narrow to place its orders at least one price tick apart.
- **`LADDER_LEVELS_INVALID`** · 272 · HTTP 400 · `invalid_argument`\
  A ladder places from 2 to 100 orders.
- **`ATTACHED_EXIT_WORKING`** · 292 · HTTP 400 · `failed_precondition`\
  An exit order placed by one of the order's attached take-profit or stop legs is still working, so the order's attached legs can't be added, edited, paused or resumed now; removing a leg is still accepted. Nothing changed; retry once the exit completes.
- **`MARKET_TRIGGER_LIMIT_EXCEEDED`** · 293 · HTTP 429 · `resource_exhausted`\
  The account already has the most triggers one account may have on this market, attached take-profit, stop-loss and trailing legs included. Nothing changed; retry once one of them ends.
- **`MARKET_TWAP_LIMIT_EXCEEDED`** · 294 · HTTP 429 · `resource_exhausted`\
  The account already has the most TWAP orders one account may have on this market. Nothing changed; retry once one of them ends.
- **`MARKET_LADDER_LIMIT_EXCEEDED`** · 295 · HTTP 429 · `resource_exhausted`\
  The account already has the most ladder orders one account may have on this market. Nothing changed; retry once one of them ends.
- **`CHILD_QTY_EXCEEDS_REMAINING`** · 296 · HTTP 400 · `invalid_argument`\
  The new quantity of a TWAP order's slice would leave more than the TWAP's remaining quantity. Nothing changed; a slice can be raised up to what the TWAP still has to execute.
- **`TRIGGER_WOULD_TRIGGER_IMMEDIATELY`** · 302 · HTTP 400 · `failed_precondition`\
  The change would act on the trigger at once. The new trigger price of a stop-loss or take-profit, or the trigger price a new trailing distance gives an activated trailing stop, is already reached by the price the trigger watches (at or past it), so the trigger would fire at once and send its order; or the new activation price of a trailing stop not yet activated is already reached by that price, so it would activate at once. Nothing changed; the trigger keeps its previous settings. Returned by ModifyTrigger, and by an order modify that moves an attached take-profit, stop-loss or trailing stop of an order with a fill. Choose a price the market has not reached.
- **`TRIGGER_SYMBOL_MISMATCH`** · 305 · HTTP 400 · `invalid_argument`\
  The request names a listed trading pair other than the trigger's own, so it was refused. Nothing changed; name the trigger's own pair, or omit the symbol. A pair that is not listed is `ERROR_CODE_UNKNOWN_SYMBOL`.

### QuickSwap orders

- **`QUICKSWAP_NOT_PERMITTED`** · 203 · HTTP 403 · `permission_denied`\
  The request carried QuickSwap terms that the account or market does not accept.
- **`QUICKSWAP_FEE_DETAILS_INCOMPLETE`** · 276 · HTTP 400 · `invalid_argument`\
  The request's QuickSwap fee details are incomplete: a fee schedule needs a broker, and a broker or broker fee terms need a fee schedule.
- **`QUICKSWAP_MARKET_NOT_PRICED`** · 277 · HTTP 400 · `failed_precondition`\
  The requested QuickSwap fee schedule doesn't price this market.
- **`QUICKSWAP_BROKER_FEE_TERMS_MISMATCH`** · 278 · HTTP 400 · `invalid_argument`\
  The broker fee terms belong to another broker.
- **`QUICKSWAP_FEE_RECIPIENT_IS_PAYER`** · 279 · HTTP 400 · `invalid_argument`\
  A QuickSwap fee would be paid into the account placing the order.
- **`QUICKSWAP_BROKER_FEE_TERMS_UNAVAILABLE`** · 280 · HTTP 503 · `unavailable`\
  The broker fee terms aren't available yet; retry shortly.
- **`QUICKSWAP_BROKER_ACCOUNT_UNAVAILABLE`** · 281 · HTTP 503 · `unavailable`\
  The broker's fee account isn't available yet; retry shortly.
- **`QUICKSWAP_DISABLED`** · 282 · HTTP 400 · `failed_precondition`\
  QuickSwap isn't enabled for this account's trading.
- **`QUICKSWAP_ATTACHED_RISK_NOT_ALLOWED`** · 283 · HTTP 400 · `invalid_argument`\
  QuickSwap orders can't carry take-profit or stop-loss legs.
- **`QUICKSWAP_ORDER_NOT_MODIFIABLE`** · 284 · HTTP 400 · `failed_precondition`\
  QuickSwap orders can't be amended or replaced.
- **`QUICKSWAP_FEE_TOTAL_TOO_HIGH`** · 285 · HTTP 400 · `failed_precondition`\
  The QuickSwap fees together would exceed the order's value.
- **`QUICKSWAP_BROKER_FEE_TERMS_INVALID`** · 286 · HTTP 400 · `failed_precondition`\
  The broker fee terms are invalid and can't be used.
- **`QUICKSWAP_BROKER_INVALID`** · 287 · HTTP 400 · `failed_precondition`\
  The broker's QuickSwap setup is invalid and can't be used.
- **`QUICKSWAP_FEE_SCHEDULE_INVALID`** · 288 · HTTP 400 · `failed_precondition`\
  The QuickSwap fee schedule is invalid and can't be used.
- **`QUICKSWAP_MARKET_FEE_INVALID`** · 289 · HTTP 400 · `failed_precondition`\
  The QuickSwap fee for this market is invalid and can't be used.
- **`QUICKSWAP_SETUP_INVALID`** · 290 · HTTP 400 · `failed_precondition`\
  QuickSwap's setup is invalid, so QuickSwap orders can't be placed.
- **`QUICKSWAP_CAPACITY_REACHED`** · 291 · HTTP 429 · `resource_exhausted`\
  QuickSwap's capacity for fee settings is reached; this order can't be placed.
- **`QUICKSWAP_ACCOUNT_OWNER_UNKNOWN`** · 301 · HTTP 503 · `unavailable`\
  The QuickSwap account is not ready yet; no order was placed. Retry shortly.

### Rate limits and capacity

- **`OVERLOADED`** · 67 · HTTP 503 · `resource_exhausted`\
  The account already has its maximum order requests in flight; nothing was admitted. ConnectRPC returns `RESOURCE_EXHAUSTED` (HTTP 429); REST returns HTTP 503. No Retry-After or RateLimit-\* headers are supplied. Retry after one of the outstanding requests completes.
- **`RATE_LIMIT_EXCEEDED`** · 69 · HTTP 429 · `resource_exhausted`\
  The account exhausted its current order-admission quota.
- **`PAIR_BACKLOGGED`** · 207 · HTTP 503 · `unavailable`\
  The trading pair is busy with the account's earlier requests, so this one was not admitted and nothing was reserved. Retry shortly.
- **`PRICE_LEVELS_EXHAUSTED`** · 208 · HTTP 429 · `resource_exhausted`\
  The order book of the market holds its maximum number of distinct price levels, so an order at a new price cannot rest. Nothing changed.
- **`CLIENT_ORDER_IDS_EXHAUSTED`** · 209 · HTTP 429 · `resource_exhausted`\
  The account reserves its maximum number of client order IDs, including those of recently ended orders. Retry once they expire, or send the request without a client order ID.
- **`ORDER_SEQUENCE_EXHAUSTED`** · 218 · HTTP 429 · `resource_exhausted`\
  The account used every order identifier available to it in this market. Retrying does not help; contact support.
- **`RATE_LIMIT_POLICY_UNAVAILABLE`** · 224 · HTTP 503 · `unavailable`\
  No usable rate-limit policy applies to the account right now, so the request was refused rather than admitted unlimited. Retry later.
- **`SYSTEM_RATE_LIMITED`** · 225 · HTTP 429 · `resource_exhausted`\
  The venue-wide admission rate that the account shares with other accounts is exhausted. The account's own limit was not reached; retry shortly.
- **`REQUEST_RECEIPTS_EXHAUSTED`** · 231 · HTTP 429 · `resource_exhausted`\
  The account keeps its maximum number of recent modify or batch requests for duplicate detection. Retry once earlier ones expire.
- **`NEW_ACCOUNT_CAPACITY_REACHED`** · 235 · HTTP 429 · `resource_exhausted`\
  The venue holds its maximum number of account access records, so an account trading this market for the first time cannot be admitted. Retry later.

### Service availability

- **`UNAVAILABLE`** · 10 · HTTP 503 · `unavailable`\
  Service is temporarily unavailable.
- **`UPSTREAM_ERROR`** · 14 · HTTP 502 · `unavailable`\
  Upstream dependency returned an error.
- **`INTERNAL_ERROR`** · 18 · HTTP 500 · `internal`\
  Order processing failed because of an unexpected error.
- **`GATEWAY_MISCONFIGURED`** · 77 · HTTP 500 · `internal`\
  The trading gateway that took the request is misconfigured for the order service behind it. An operator must correct it; retrying does not help.
- **`FEE_SCHEDULE_UNAVAILABLE`** · 220 · HTTP 503 · `unavailable`\
  The fees that apply to the order cannot be determined right now, so it was not admitted. Retry later.
- **`POLICY_UNAVAILABLE`** · 221 · HTTP 503 · `unavailable`\
  The account's trading policy cannot be evaluated right now, so the order was not admitted. Retry later.

### More specific REST codes for orders

Some REST responses carry a more specific `code` than the enum value that ConnectRPC returns in `ErrorDetail`. The number in each entry is the enum value both interfaces share.

- **`REQUEST_TOO_LARGE`** · same as `BAD_REQUEST` (1) · HTTP 413 · `invalid_argument`\
  Returned by Reads, writes.
- **`INVALID_BEFORE_TS_NS`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_END_TIME`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_LIMIT`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_OFFSET`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_ORDER_STATUS`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_PAGE_TOKEN`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_SIDE`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_START_TIME`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_SUBACCOUNT_ID`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_SYMBOL`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_TRIGGER_ID`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_TRIGGER_STATUS`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`INVALID_TRIGGER_TYPE`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`ORDER_ID_REQUIRED`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`TRAILING_STOP_ORDER_TYPE_UNSUPPORTED`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Writes.
- **`TRIGGER_ID_REQUIRED`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`VALIDATION_ERROR`** · same as `INVALID_ARGUMENT` (2) · HTTP 400 · `invalid_argument`\
  Returned by Reads.
- **`ROLE_SPOT_TRADE_DENY`** · same as `PERMISSION_DENIED` (12) · HTTP 403 · `permission_denied`\
  Returned by Writes.

## Withdrawals

Enum `chain.withdraw.v1.ErrorCode`, prefix `ERROR_CODE_`. Withdrawals from a Trading account to the Funding account or to another Network, destination validation, and auto-withdraw rules.

- **`INSUFFICIENT_FUNDS`** · 1 · HTTP 400 · `failed_precondition`\
  The source account does not have enough available Trading balance.
- **`INVALID_REQUEST`** · 2 · HTTP 400 · `invalid_argument`\
  Request payload or one of its fields is invalid.
- **`UNAUTHENTICATED`** · 3 · HTTP 401 · `unauthenticated`\
  Caller is not authenticated.
- **`PERMISSION_DENIED`** · 4 · HTTP 403 · `permission_denied`\
  Caller is not permitted to perform the withdraw operation.
- **`RATE_LIMIT_EXCEEDED`** · 5 · HTTP 429 · `resource_exhausted`\
  Request exceeded the applicable admission rate limit.
- **`SERVICE_UNAVAILABLE`** · 6 · HTTP 503 · `unavailable`\
  A required dependency is temporarily unavailable.
- **`INTERNAL_ERROR`** · 7 · HTTP 500 · `internal`\
  The request failed because of an unexpected server error.
- **`INVALID_SUBACCOUNT_ID`** · 8 · HTTP 400 · `invalid_argument`\
  The selected subaccount identifier is invalid.
- **`SUBACCOUNT_NOT_FOUND`** · 9 · HTTP 404 · `not_found`\
  The selected subaccount does not exist.
- **`INVALID_ACTION`** · 10 · HTTP 400 · `invalid_argument`\
  The requested withdraw action is invalid for this endpoint.
- **`UNSUPPORTED_LEDGER`** · 11 · HTTP 400 · `invalid_argument`\
  The requested ledger is not supported for withdrawals.
- **`UNSUPPORTED_ASSET`** · 12 · HTTP 400 · `invalid_argument`\
  The requested asset or withdraw route is not supported.
- **`INVALID_AMOUNT`** · 13 · HTTP 400 · `invalid_argument`\
  The withdraw amount is invalid.
- **`INVALID_DESTINATION_CHAIN`** · 14 · HTTP 400 · `invalid_argument`\
  The destination chain is invalid.
- **`INVALID_DESTINATION_ADDRESS`** · 15 · HTTP 400 · `invalid_argument`\
  The destination address is invalid.
- **`EXTERNAL_DESTINATION_NOT_WHITELISTED`** · 16 · HTTP 403 · `permission_denied`\
  The external destination is not whitelisted.
- **`INTERNAL_RECIPIENT_NOT_WHITELISTED`** · 17 · HTTP 403 · `permission_denied`\
  The internal funding recipient is not whitelisted.
- **`AMOUNT_BELOW_MINIMUM`** · 18 · HTTP 400 · `invalid_argument`\
  The withdraw amount is below the configured minimum including fees.
- **`AMOUNT_EXCEEDS_SUPPLY`** · 19 · HTTP 400 · `invalid_argument`\
  The withdraw amount exceeds the available zipped-asset supply.
- **`SOURCE_SMART_ACCOUNT_UNAVAILABLE`** · 20 · HTTP 400 · `failed_precondition`\
  The source smart-account address is unavailable.
- **`SIGNATURE_REQUIRED`** · 21 · HTTP 400 · `invalid_argument`\
  The required payload signature is missing.
- **`SIGNATURE_SCHEME_UNSUPPORTED`** · 22 · HTTP 400 · `invalid_argument`\
  The requested signature scheme is unsupported.
- **`SIGNER_WALLET_INVALID`** · 23 · HTTP 400 · `invalid_argument`\
  The wallet supplied as signer is invalid.
- **`WALLET_BINDING_INVALID`** · 24 · HTTP 403 · `permission_denied`\
  Wallet authorization binding verification failed.
- **`WALLET_BINDING_SCOPE_MISMATCH`** · 25 · HTTP 403 · `permission_denied`\
  Wallet authorization binding does not cover the requested scope.
- **`WALLET_BINDING_SIGNER_MISMATCH`** · 26 · HTTP 403 · `permission_denied`\
  Wallet authorization binding does not match the signer.
- **`API_KEY_NOT_FOUND`** · 27 · HTTP 403 · `permission_denied`\
  The API key could not be resolved.
- **`API_KEY_BINDING_INVALID`** · 28 · HTTP 403 · `permission_denied`\
  API-key authorization binding verification failed.
- **`API_KEY_BINDING_SCOPE_MISMATCH`** · 29 · HTTP 403 · `permission_denied`\
  API-key authorization binding does not cover the requested scope.
- **`API_KEY_BINDING_PUBLIC_KEY_MISMATCH`** · 30 · HTTP 403 · `permission_denied`\
  API-key authorization binding does not match the configured public key.
- **`IDEMPOTENCY_CONFLICT`** · 31 · HTTP 409 · `already_exists`\
  The idempotency key was reused with different request data.
- **`FUNDS_LOCK_CONFLICT`** · 32 · HTTP 409 · `aborted`\
  The funds lock conflicts with an existing or finalized reservation.
- **`CAPITAL_VIEW_UNAVAILABLE`** · 33 · HTTP 503 · `unavailable`\
  The authoritative capital view is not ready or is stale.
- **`CHAIN_METADATA_UNAVAILABLE`** · 34 · HTTP 503 · `unavailable`\
  Required chain or contract metadata is unavailable.
- **`FEE_UNAVAILABLE`** · 35 · HTTP 503 · `unavailable`\
  Required network fee data is unavailable.
- **`SUPPLY_UNAVAILABLE`** · 36 · HTTP 503 · `unavailable`\
  Required zipped-asset supply data is unavailable.
- **`STEP_UP_UNAVAILABLE`** · 37 · HTTP 503 · `unavailable`\
  Fresh step-up verification is temporarily unavailable.
- **`DESTINATION_VALIDATION_UNAVAILABLE`** · 38 · HTTP 503 · `unavailable`\
  Destination validation is temporarily unavailable.
- **`ACCOUNT_SHARD_UNAVAILABLE`** · 39 · HTTP 503 · `unavailable`\
  Funds movement for this account is temporarily unavailable. Retry later.
- **`FAILED_PRECONDITION`** · 40 · HTTP 400 · `failed_precondition`\
  A required precondition was not satisfied.
- **`NOT_FOUND`** · 41 · HTTP 404 · `not_found`\
  The requested resource was not found.
- **`CONFLICT`** · 42 · HTTP 409 · `aborted`\
  The request conflicts with existing state.
- **`INVALID_AUTO_WITHDRAW_SCHEDULE`** · 43 · HTTP 400 · `invalid_argument`\
  The auto-withdraw schedule is invalid: a field its cadence needs is missing or out of range, or a field of another cadence is set.
- **`AMOUNT_EXCEEDS_ROUTE_PRECISION`** · 44 · HTTP 400 · `invalid_argument`\
  The withdraw amount has more decimal places than the destination network's token supports (AssetChainVariant.`source_decimals`). Round `amount_e18` down to a whole number of that token's smallest units before signing.

## Internal transfers

Enum `transfer.v1.ErrorCode`, prefix `ERROR_CODE_`. Transfers between Trading accounts.

- **`INSUFFICIENT_FUNDS`** · 1 · HTTP 400 · `failed_precondition`\
  The source account does not have enough available Trading balance.
- **`INVALID_REQUEST`** · 2 · HTTP 400 · `invalid_argument`\
  Request payload or one of its fields is invalid.
- **`UNAUTHENTICATED`** · 3 · HTTP 401 · `unauthenticated`\
  Caller is not authenticated.
- **`PERMISSION_DENIED`** · 4 · HTTP 403 · `permission_denied`\
  Caller is not permitted to create the transfer.
- **`RATE_LIMIT_EXCEEDED`** · 5 · HTTP 429 · `resource_exhausted`\
  Request exceeded the applicable admission rate limit.
- **`SERVICE_UNAVAILABLE`** · 6 · HTTP 503 · `unavailable`\
  A required dependency is temporarily unavailable.
- **`INTERNAL_ERROR`** · 7 · HTTP 500 · `internal`\
  The request failed because of an unexpected server error.
- **`INVALID_SUBACCOUNT_ID`** · 8 · HTTP 400 · `invalid_argument`\
  The selected subaccount identifier is invalid.
- **`SUBACCOUNT_NOT_FOUND`** · 9 · HTTP 404 · `not_found`\
  The selected subaccount does not exist.
- **`SOURCE_ACCOUNT_INACTIVE`** · 10 · HTTP 400 · `failed_precondition`\
  The source subaccount is not active.
- **`UNSUPPORTED_ASSET`** · 11 · HTTP 400 · `invalid_argument`\
  The requested asset is not supported for internal transfers.
- **`INVALID_AMOUNT`** · 12 · HTTP 400 · `invalid_argument`\
  The transfer amount is invalid.
- **`INVALID_DESTINATION`** · 13 · HTTP 400 · `invalid_argument`\
  The destination identifier is invalid.
- **`DESTINATION_NOT_FOUND`** · 14 · HTTP 404 · `not_found`\
  The destination account or smart account could not be found.
- **`DESTINATION_INACTIVE`** · 15 · HTTP 400 · `failed_precondition`\
  The destination subaccount is not active.
- **`SAME_SOURCE_DESTINATION`** · 16 · HTTP 400 · `invalid_argument`\
  Source and destination resolve to the same account.
- **`DESTINATION_NOT_WHITELISTED`** · 17 · HTTP 403 · `permission_denied`\
  The destination is not present on the caller's internal whitelist.
- **`SMART_ACCOUNT_UNAVAILABLE`** · 18 · HTTP 400 · `failed_precondition`\
  A required source or destination smart-account address is unavailable.
- **`STEP_UP_UNAVAILABLE`** · 19 · HTTP 503 · `unavailable`\
  Fresh step-up verification is temporarily unavailable.
- **`IDEMPOTENCY_CONFLICT`** · 20 · HTTP 409 · `already_exists`\
  The idempotency key was reused with different request data.
- **`FUNDS_LOCK_CONFLICT`** · 21 · HTTP 409 · `aborted`\
  The funds lock conflicts with an existing or finalized reservation.
- **`CAPITAL_VIEW_UNAVAILABLE`** · 22 · HTTP 503 · `unavailable`\
  The authoritative capital view is not ready or is stale.
- **`ACCOUNT_SHARD_UNAVAILABLE`** · 23 · HTTP 503 · `unavailable`\
  Funds movement for this account is temporarily unavailable. Retry later.
- **`POLICY_DENIED`** · 24 · HTTP 403 · `permission_denied`\
  A required account or API-key policy rejected the transfer.
- **`FAILED_PRECONDITION`** · 25 · HTTP 400 · `failed_precondition`\
  A required precondition was not satisfied.
- **`NOT_FOUND`** · 26 · HTTP 404 · `not_found`\
  The requested resource was not found.
- **`CONFLICT`** · 27 · HTTP 409 · `aborted`\
  The request conflicts with existing state.

## Accounts, API keys, and security

Enum `auth.v1.AuthErrorCode`. Login, Subaccounts, members and invites, API keys, policies, MFA, and step-up. The REST `code` is the enum name.

- **`AUTH_USERNAME_INVALID`** · 1 · HTTP 400 · `invalid_argument`\
  Username format or characters are invalid.
- **`AUTH_USERNAME_TAKEN`** · 2 · HTTP 409 · `already_exists`\
  Username is already used by another account.
- **`AUTH_USERNAME_COOLDOWN`** · 3 · HTTP 412 · `failed_precondition`\
  Username was changed too recently.
- **`AUTH_USERNAME_FEATURE_LOCKED`** · 4 · HTTP 403 · `failed_precondition`, `permission_denied`\
  Account is not currently eligible to claim or change a username.
- **`AUTH_USERNAME_RESERVED`** · 5 · HTTP 403 · `permission_denied`\
  Username is reserved and cannot be claimed by this account.
- **`AUTH_INVALID_REQUEST`** · 6 · HTTP 400 · `failed_precondition`, `invalid_argument`\
  Request is malformed or missing required input.
- **`AUTH_AUTHENTICATION_REQUIRED`** · 7 · HTTP 401 · `unauthenticated`\
  Authentication is required for this operation.
- **`AUTH_SESSION_KIND_NOT_ALLOWED`** · 8 · HTTP 403 · `permission_denied`\
  Presented session type is not allowed for this operation.
- **`AUTH_WALLET_LOGIN_FAILED`** · 9 · HTTP 401 · `unauthenticated`\
  Wallet login failed because the nonce or signature could not be verified.
- **`AUTH_RESOURCE_NOT_FOUND`** · 10 · HTTP 404 · `not_found`\
  Requested resource was not found.
- **`AUTH_SUBACCOUNT_ACCESS_DENIED`** · 11 · HTTP 403 · `permission_denied`\
  Caller does not have access to the requested sub-account.
- **`AUTH_API_KEY_ACCESS_DENIED`** · 12 · HTTP 403 · `permission_denied`\
  Caller does not have access to the requested API key.
- **`AUTH_API_KEY_INVALID_STATUS_TRANSITION`** · 14 · HTTP 400 · `invalid_argument`\
  Requested API key status transition is not allowed.
- **`AUTH_POLICY_INVALID`** · 15 · HTTP 400 · `invalid_argument`\
  Policy definition or binding is invalid.
- **`AUTH_SMART_ACCOUNT_ALREADY_LINKED`** · 16 · HTTP 409 · `already_exists`\
  Smart-account address is already linked to another account.
- **`AUTH_INVITE_ACCESS_DENIED`** · 17 · HTTP 403 · `permission_denied`\
  Caller does not have access to the requested invite.
- **`AUTH_INVITE_INVALID_STATE`** · 18 · HTTP 412 · `failed_precondition`, `invalid_argument`\
  Invite cannot be used in its current state.
- **`AUTH_MFA_DISABLED`** · 19 · HTTP 503 · `unavailable`\
  MFA is not available for this account.
- **`AUTH_MFA_NOT_ENROLLED`** · 20 · HTTP 412 · `failed_precondition`\
  Required MFA factor is not enrolled.
- **`AUTH_MFA_SESSION_INVALID`** · 21 · HTTP 412 · `failed_precondition`\
  MFA session is missing, expired, or invalid.
- **`AUTH_MFA_CHALLENGE_NOT_FOUND`** · 22 · HTTP 404 · `not_found`\
  MFA challenge was not found.
- **`AUTH_MFA_CHALLENGE_INVALID`** · 23 · HTTP 403 · `permission_denied`\
  MFA challenge payload is invalid.
- **`AUTH_MFA_CHALLENGE_LOCKED`** · 24 · HTTP 429 · `resource_exhausted`\
  MFA challenge is locked after too many failed attempts.
- **`AUTH_MFA_OTP_INVALID`** · 25 · HTTP 403 · `permission_denied`\
  One-time password is invalid.
- **`AUTH_MFA_RECOVERY_INVALID`** · 26 · HTTP 403 · `permission_denied`\
  Recovery code is invalid.
- **`AUTH_MFA_PASSKEY_NOT_AVAILABLE`** · 27 · HTTP 412 · `failed_precondition`\
  Passkey verification is not available for this challenge.
- **`AUTH_MFA_PASSKEY_CREDENTIAL_INVALID`** · 28 · HTTP 400 · `invalid_argument`\
  Passkey credential is invalid for this account or challenge.
- **`AUTH_MFA_PASSKEY_VERIFY_FAILED`** · 29 · HTTP 403 · `permission_denied`\
  Passkey verification failed.
- **`AUTH_MFA_ENROLLMENT_BINDING_INVALID`** · 30 · HTTP 403 · `permission_denied`\
  MFA enrollment binding is invalid or expired.
- **`AUTH_STEP_UP_REQUIRED`** · 31 · HTTP 403 · `permission_denied`\
  A fresh step-up proof is required for this protected operation.
- **`AUTH_STEP_UP_PROOF_UNAVAILABLE`** · 32 · HTTP 403 · `permission_denied`\
  A requested step-up proof is unavailable.
- **`AUTH_STEP_UP_ALREADY_CLAIMED`** · 33 · HTTP 403 · `permission_denied`\
  The step-up proof has already been claimed.
- **`AUTH_POLICY_IN_USE`** · 34 · HTTP 412 · `failed_precondition`\
  The requested policy cannot be removed because it is still in use.
- **`AUTH_POLICY_LOCKED`** · 35 · HTTP 412 · `failed_precondition`\
  The requested policy is locked against this mutation.
- **`AUTH_POLICY_SCOPE_MISMATCH`** · 36 · HTTP 412 · `failed_precondition`\
  The requested policy does not belong to the target account scope.
- **`AUTH_REVISION_CONFLICT`** · 37 · HTTP 409 · `aborted`\
  The resource changed after the caller read it.
- **`AUTH_MFA_ELEVATION_REQUIRED`** · 38 · HTTP 403 · `permission_denied`\
  A recently MFA-elevated interactive session is required.
- **`AUTH_MFA_LAST_FACTOR_REQUIRED`** · 39 · HTTP 412 · `failed_precondition`\
  At least one active MFA factor must remain enrolled.
- **`AUTH_INTERNAL_ERROR`** · 40 · HTTP 500 · `internal`\
  An unexpected internal failure prevented the auth mutation from completing.
- **`AUTH_TERMS_NOT_ACCEPTED`** · 41 · HTTP 412 · `failed_precondition`\
  The caller has not accepted the terms required for this action.
- **`AUTH_SOCIAL_VERIFICATION_EXPIRED`** · 42 · HTTP 412 · `failed_precondition`\
  Social verification challenge expired. Start a new verification, then mark it ready again.
- **`AUTH_SOCIAL_VERIFICATION_INVALID_STATE`** · 43 · HTTP 412 · `failed_precondition`\
  Social verification cannot accept a ready mark in its current state.
- **`AUTH_SUBACCOUNT_CHALLENGE_INVALID`** · 44 · HTTP 412 · `failed_precondition`\
  Sub-account authorization is expired, replaced, consumed, or has an invalid signature. Temporary verification failures return Unavailable; retry the same signed challenge.
- **`AUTH_SOCIAL_ACCOUNT_ALREADY_LINKED`** · 45 · in a response field\
  Social account is already linked to another Polyester account.
- **`AUTH_TEMPORARILY_UNAVAILABLE`** · 46 · HTTP 503 · `unavailable`\
  The request could not be completed right now and changed nothing. Retry the same request.
- **`AUTH_SUBACCOUNT_OWNER_ROLE_LOCKED`** · 47 · HTTP 412 · `failed_precondition`\
  The account owns this sub-account. An owner cannot be invited to it, and member role changes and member removal do not apply to the owner.
- **`AUTH_SIGNATURE_INVALID`** · 48 · HTTP 401 · `unauthenticated`\
  The API key request signature does not verify against the request, or the key is unknown. The REST problem code is `SIGNATURE_INVALID`.
- **`AUTH_TIMESTAMP_SKEW`** · 49 · HTTP 401 · `unauthenticated`\
  The API key request timestamp is malformed or too far from the server clock. Sync the clock, then sign the request again. The REST problem code is `TIMESTAMP_SKEW`.
- **`AUTH_MISSING_HEADERS`** · 50 · HTTP 401 · `unauthenticated`\
  The API key request lacks its timestamp or signature header. The REST problem code is `MISSING_HEADERS`.
- **`AUTH_KEY_EXPIRED`** · 51 · HTTP 401 · `unauthenticated`\
  The API key has expired. The REST problem code is `KEY_EXPIRED`.
- **`AUTH_KEY_DISABLED`** · 52 · HTTP 401 · `unauthenticated`\
  The API key is disabled or revoked. The REST problem code is `KEY_DISABLED`.
- **`AUTH_IP_NOT_ALLOWED`** · 53 · HTTP 401 · `unauthenticated`\
  The API key's IP allowlist does not include the request's source address. The REST problem code is `IP_NOT_ALLOWED`.
- **`AUTH_API_KEY_NOT_ACCEPTED`** · 54 · HTTP 401 · `unauthenticated`\
  This API does not accept API keys; authenticate with a session token. The REST problem code is `API_KEY_NOT_ACCEPTED`.

## Profiles

Enum `auth.v1.ProfileErrorCode`. Profile updates. The REST `code` is the enum name.

- **`PROFILE_INVALID_FIELD`** · 1 · HTTP 400 · `invalid_argument`\
  Generic invalid field (format/characters).
- **`PROFILE_FIELD_TOO_LONG`** · 2 · HTTP 400 · `invalid_argument`\
  Field exceeds configured max length.
- **`PROFILE_URL_INVALID`** · 3 · HTTP 400 · `invalid_argument`\
  URL is syntactically invalid.
- **`PROFILE_URL_SCHEME_INVALID`** · 4 · HTTP 400 · `invalid_argument`\
  URL scheme is not allowed (e.g., non-http(s)).

## Balances and transfer history

Enum `ledger.read.v1.ErrorCode`, prefix `ERROR_CODE_`. Balance, portfolio, equity, and transfer-history reads.

- **`BAD_REQUEST`** · 1 · HTTP 400 · `invalid_argument`\
  Bad Request. REST may return `INVALID_ARGUMENT`, `MISSING_HEADERS`, `TIMESTAMP_SKEW`.
- **`UNAUTHENTICATED`** · 2 · HTTP 401 · `unauthenticated`\
  Ledger reads require a valid bearer JWT or signed API-key request. REST may return `IP_NOT_ALLOWED`, `KEY_DISABLED`, `KEY_EXPIRED`, `SIGNATURE_INVALID`.
- **`PERMISSION_DENIED`** · 3 · HTTP 403 · `permission_denied`\
  Permission Denied. REST may return `API_KEY_ACTION_DENY`, `API_KEY_POLICY_NOT_FOUND`, `API_KEY_POLICY_REQUIRED`, `API_KEY_ROOT_SCOPE_ONLY`, `API_KEY_SUBACCOUNT_MISMATCH`, `API_KEY_UNKNOWN`, `ROLE_ACTION_DENY`, `SUBACCOUNT_POLICY_DENY`, `SUBACCOUNT_READ_FORBIDDEN`.
- **`NOT_FOUND`** · 4 · HTTP 404 · `not_found`\
  Not Found.
- **`MISSING_ACCOUNT_ID`** · 5 · HTTP 400 · `invalid_argument`\
  Missing or invalid account identifier (legacy; used by older endpoints).
- **`INVALID_ACCOUNT_ID`** · 6 · HTTP 400 · `invalid_argument`\
  Invalid Account ID.
- **`MISSING_WALLET`** · 7 · HTTP 400 · `invalid_argument`\
  Wallet-specific errors for balance lookups by wallet.
- **`WALLET_RESOLUTION_UNAVAILABLE`** · 8 · HTTP 502 · `unavailable`\
  Wallet Resolution Unavailable.
- **`WALLET_NOT_FOUND`** · 9 · HTTP 404 · `not_found`\
  Wallet Not Found.
- **`UPSTREAM_ERROR`** · 10 · HTTP 502 · `unavailable`\
  Upstream dependency error (e.g., transfers store, wallet resolver).
- **`INVALID_SUBACCOUNT_ID`** · 11 · HTTP 400 · `invalid_argument`\
  `subaccount_id` is zero or not an encoded public subaccount identifier.

## Market overview

Enum `marketoverview.v1.ErrorCode`, prefix `ERROR_CODE_`. Market overview reads.

- **`BAD_REQUEST`** · 1 · HTTP 400 · `invalid_argument`\
  Bad request.
- **`INVALID_ARGUMENT`** · 2 · HTTP 400 · `invalid_argument`\
  Invalid argument.
- **`NOT_FOUND`** · 3 · HTTP 404 · `not_found`\
  Not found.
- **`UNAVAILABLE`** · 4 · HTTP 503 · `unavailable`\
  Service unavailable.
- **`UPSTREAM_ERROR`** · 5 · HTTP 502 · `unavailable`\
  Upstream error.

## Daily claim

Enum `claims.v1.ErrorCode`, prefix `ERROR_CODE_`. Daily campaign reward status and claims.

- **`CLAIM_TEMPORARILY_UNAVAILABLE`** · 1 · HTTP 503 · `unavailable`\
  The claim reward is temporarily unavailable. Please try again later.
- **`UNAUTHENTICATED`** · 2 · HTTP 401 · `unauthenticated`\
  A valid session is required. API keys cannot access claims.
- **`RATE_LIMIT_EXCEEDED`** · 3 · HTTP 429 · `resource_exhausted`\
  The applicable request rate limit was exceeded.
- **`CLAIM_UNAVAILABLE`** · 4 · HTTP 400 · `failed_precondition`\
  No reward is available for the current UTC day.
- **`CONFLICT`** · 5 · HTTP 409 · `aborted`\
  The request encountered concurrent claim activity. Retry the request.
- **`INVALID_REQUEST`** · 6 · HTTP 400 · `invalid_argument`\
  The request payload is invalid.
- **`REQUEST_TOO_LARGE`** · 7 · HTTP 413 · `resource_exhausted`\
  The REST request body exceeds the 1 KiB limit.
- **`SERVICE_UNAVAILABLE`** · 8 · HTTP 503 · `unavailable`\
  The service is temporarily unable to complete the request.
- **`INTERNAL_ERROR`** · 9 · HTTP 500 · `internal`\
  The request failed because of an unexpected server error.
- **`PERMISSION_DENIED`** · 10 · HTTP 403 · `permission_denied`\
  The claim request was not permitted.
- **`FAILED_PRECONDITION`** · 11 · HTTP 400 · `failed_precondition`\
  A required condition for completing the claim was not satisfied.
- **`SOCIAL_VERIFICATION_REQUIRED`** · 12 · HTTP 400 · `failed_precondition`\
  Verify an X or Discord account before claiming a reward.
- **`SUBACCOUNT_NOT_FOUND`** · 13 · HTTP 404 · `not_found`\
  The selected subaccount does not exist or is not owned by the authenticated root account.
- **`SUBACCOUNT_INACTIVE`** · 14 · HTTP 400 · `failed_precondition`\
  The selected subaccount is owned by the authenticated root account but is not active.
- **`CLAIM_PAYOUT_UNAVAILABLE`** · 15 · HTTP 503 · `unavailable`\
  Reward payouts for this campaign are paused. Today's claim is kept and paid automatically once payouts resume.

## Swap

Enum `swap.v1.ErrorCode`. Swap quotes and executions. ConnectRPC only, so there is no HTTP status.

- **`ROUTE_UNSUPPORTED`** · 1 · `failed_precondition`\
  No spot market trades the source asset directly against the destination asset.
- **`AMOUNT_OUT_OF_RANGE`** · 2 · `invalid_argument`\
  The amount is outside the market's current limits. The error carries the limits (`min_amount_e18`, `max_amount_e18`) when known.
- **`QUOTE_UNAVAILABLE`** · 3 · `unavailable`\
  No price is currently available for the route; retry later.
- **`PROTECTION_UNACHIEVABLE`** · 4 · `failed_precondition`\
  Current order-book depth cannot deliver `min_amount_out_e18` (or the requested slippage): request a new quote.
- **`QUOTE_EXPIRED`** · 5 · `failed_precondition`\
  `quote_expires_at` has passed: request a new quote.
- **`IDEMPOTENCY_CONFLICT`** · 6 · `already_exists`\
  The idempotency key was already used with a different request. The error carries the original `swap_id`.
- **`SWAP_NOT_FOUND`** · 7 · `not_found`\
  No Swap of the caller matches the selector.
- **`INVALID_SUBACCOUNT_ID`** · 8 · `invalid_argument`\
  `subaccount_id` is not a valid sub-account ID.
- **`SUBACCOUNT_NOT_FOUND`** · 9 · `not_found`\
  The sub-account does not exist.
- **`SUBACCOUNT_INACTIVE`** · 10 · `failed_precondition`\
  The sub-account is not active.
- **`SWAP_NOT_PERMITTED`** · 11 · `permission_denied`\
  The caller may not Swap on the account: the role, the API key's policy or the sub-account's policy does not grant SWAP, or a root-scoped API key selected a sub-account.
- **`SERVICE_UNAVAILABLE`** · 12 · `unavailable`\
  A required service is temporarily unavailable; retry the same request.
- **`DIRECTION_UNSUPPORTED`** · 13 · `failed_precondition`\
  The market trades the two assets but cannot execute a Swap in this direction: a buy there would pay its fee in the asset it spends.

## QuickSwap broker API

Enum `swap.quickswap.v1.ErrorCode`. QuickSwap quotes, creates, and broker administration.

- **`ROUTE_UNSUPPORTED`** · 1 · HTTP 400 · `failed_precondition`\
  The source and destination route is not offered, or a bridge was requested with TWAP execution.
- **`AMOUNT_OUT_OF_RANGE`** · 2 · HTTP 400 · `invalid_argument`\
  The amount is outside the route's current limits. The error carries the limits (`min_deposit_amount`, `max_deposit_amount`) when known.
- **`DECIMALS_MISMATCH`** · 3 · HTTP 400 · `invalid_argument`\
  An amount's decimals do not match its route's token decimals.
- **`DESTINATION_ADDRESS_INVALID`** · 4 · HTTP 400 · `invalid_argument`\
  `destination_address` or `destination_memo` is not valid on the destination network.
- **`RETURN_ADDRESS_INVALID`** · 5 · HTTP 400 · `invalid_argument`\
  `return_address` or `return_memo` is not valid on the source network.
- **`REFUND_ADDRESS_REQUIRED`** · 6 · HTTP 400 · `failed_precondition`\
  The route has an intermediate asset and no refund address was supplied.
- **`REFUND_ADDRESS_INVALID`** · 7 · HTTP 400 · `invalid_argument`\
  `refund_zipped_asset_id` is not a withdraw route of the intermediate asset, or `refund_address` or `refund_memo` is not valid on its network.
- **`SOURCE_WALLET_INVALID`** · 8 · HTTP 400 · `invalid_argument`\
  `source_wallet` is not valid on the source network.
- **`QUOTE_UNAVAILABLE`** · 11 · HTTP 503 · `unavailable`\
  No price is currently available for the route; retry later.
- **`PROTECTION_UNACHIEVABLE`** · 12 · HTTP 400 · `failed_precondition`\
  The protection cannot be met at the current price: a `min_amount_out` above the expected output, or an order book that cannot fill the protected execution at the quoted prices.
- **`ADDRESS_UNAVAILABLE`** · 13 · HTTP 503 · `unavailable`\
  No deposit address is available right now. The QuickSwap (`swap_id` in the error) is kept, and its address is allocated automatically when one frees up. Follow it with GetQuickSwap or by repeating the request unchanged. Its quote stays the one priced at creation, and its funding window starts when the address is issued (`issued_at`).
- **`IDEMPOTENCY_CONFLICT`** · 14 · HTTP 409 · `already_exists`\
  The idempotency key was already used with a different request.
- **`SWAP_NOT_FOUND`** · 15 · HTTP 404 · `not_found`\
  No QuickSwap of this broker matches the selector.
- **`BROKER_DISABLED`** · 18 · HTTP 403 · `permission_denied`\
  The broker is disabled: quotes and creates are refused. Reads and QuickSwaps already created continue.
- **`BROKER_LIMIT`** · 19 · HTTP 429 · `resource_exhausted`\
  A broker limit was reached: the unfunded QuickSwaps held at once, the QuickSwaps created per hour, the request rate of the API key, or the affiliate vaults the broker may create. Nothing is bound to the key. A funded or expired QuickSwap frees an unfunded slot; when the response carries a Retry-After header, retry after that many seconds.
- **`AFFILIATE_VAULT_UNKNOWN`** · 20 · HTTP 400 · `failed_precondition`\
  An affiliate names a vault that is not an active affiliate vault of the broker: unknown, not yet created, disabled, another broker's, or the default vault. Nothing is bound to the key; create or enable the vault and repeat the request.
- **`BROKER_NOT_FOUND`** · 21 · HTTP 404 · `not_found`\
  No broker with this name has the caller as its key or member.
- **`ACTION_DENIED`** · 22 · HTTP 403 · `permission_denied`\
  The caller's role, or a broker API key, may not perform the action.
- **`STEP_UP_REQUIRED`** · 23 · HTTP 403 · `permission_denied`\
  The action needs a fresh step-up proof of the acting member in the X-Auth-Step-Up header, and none was sent or it was already used or expired. Complete an MFA challenge for fresh step-up and repeat the request with the new proof.
- **`VAULT_NOT_FOUND`** · 24 · HTTP 404 · `not_found`\
  The broker has no affiliate vault with this ID.
- **`KEY_NOT_FOUND`** · 25 · HTTP 404 · `not_found`\
  The broker has no API key with this ID, or it no longer works.
- **`KEY_LIMIT`** · 26 · HTTP 400 · `failed_precondition`\
  The broker would have more than two working API keys. Revoke one first.
- **`LAST_KEY`** · 27 · HTTP 400 · `failed_precondition`\
  The key is the broker's last key that works without an expiry; create another key first.
- **`MEMBER_NOT_FOUND`** · 28 · HTTP 404 · `not_found`\
  The person is not a member of the broker and has no pending invite, or the account does not exist.
- **`ALREADY_MEMBER`** · 29 · HTTP 409 · `already_exists`\
  The person is already a member of the broker.
- **`OWNER_IMMUTABLE`** · 30 · HTTP 400 · `failed_precondition`\
  The Owner cannot be removed or given another role; transfer ownership instead.
- **`INVITE_NOT_FOUND`** · 31 · HTTP 404 · `not_found`\
  No pending invite with this ID is addressed to the caller.
- **`FEES_INVALID`** · 32 · HTTP 400 · `invalid_argument`\
  The fees are not valid: more than three affiliates, an affiliate without a valid `account_id` or with bps outside 1 to 300, a vault named twice, or `broker_bps` and the affiliates' bps totalling more than 300.
- **`STATS_INCOMPLETE`** · 33 · HTTP 500 · `internal`\
  The broker stats cannot be read: a QuickSwap in the window, named by ErrorDetail.`swap_id`, is missing a record they need. Contact Polyester broker support with the `swap_id`.
- **`ADDRESS_CONFLICT`** · 34 · HTTP 409 · `aborted`\
  The QuickSwap (`swap_id` in the error) cannot be issued a deposit address and never gets one, so nothing can be deposited to it; it is EXPIRED with reason `DEPOSIT_ADDRESS_CONFLICT`. Create a new QuickSwap with a new idempotency key, and report the `swap_id` to Polyester broker support.

## Private WebSocket requests

Enum `privatews.v1.RequestError.Code`. `RequestError` frames on the private WebSocket. A request error does not close the connection.

- **`FORBIDDEN`** · 1\
  The subscribe token does not authorize this account for this connection.
- **`INVALID_REQUEST`** · 2\
  A field is missing or malformed.
- **`SUBSCRIPTION_UNKNOWN`** · 3\
  No such subscription.
- **`CURSOR_INVALID`** · 4\
  The resume cursor cannot be read.
- **`TOO_MANY_SUBSCRIPTIONS`** · 5\
  The connection already holds 64 subscriptions.
- **`BEHIND`** · 6\
  The account's live view did not catch up in time (Sync: 10 seconds).
