A rejected command is answered with a CommandReject and the connection stays open. Only an
answer without a definite outcome ends the connection, with close code 1013: an outcome-unknown
code, or UNAVAILABLE for a command that could not be sent. The reject's code tells you whether
anything changed and what to do next.
Read a CommandReject
| Field | Meaning |
|---|---|
seq, correlationId | Copied from the command; 0 when the frame could not be decoded |
code | A RejectCode value. Branch on this |
tsNs | Rejection time |
rateLimit* | Quota details for RATE_LIMIT_EXCEEDED; null or zero for rejects unrelated to rate limits |
existingOrderId | For CONFLICT_DUPLICATE_CLIENT_ORDER_ID: the order holding that client order ID, when known; 0 otherwise |
detail | UTF-8 text for logs and display. Do not parse it |
RejectCode uses the same numbers as the order error codes of the REST and ConnectRPC APIs, plus SEQUENCE_OUT_OF_ORDER (1001) for a sequence gap on the connection. The same numbers appear in
batch item results and in OrderEvent.rejectReason. The full list is in the Message reference.
Decide what to do
Most rejects change nothing. The groups below cover the codes an order-entry client meets most often; the message reference describes every code.
- Encoding or structure · state changed: no
BAD_REQUEST(1),INVALID_ARGUMENT(2),BATCH_TOO_LARGE(33),VALIDATION_ERROR(66)
Fix the client. A wrong schema version or block length isBAD_REQUEST. - Session sequence · state changed: no
SEQUENCE_OUT_OF_ORDER(1001)
Resend with the expectedseq; see Sequence numbers. - Order parameters · state changed: no
BAD_PRICE(5),BAD_QTY(6),MIN_NOTIONAL(7),QTY_STEP_SIZE(8),PRICE_TICK_SIZE(30),MIN_QTY(31),MAX_QTY(74),MAX_NOTIONAL(75),INVALID_TIME_IN_FORCE(202),FEE_ASSET_NOT_ALLOWED(15),MAX_SLIPPAGE_INVALID(48),MAX_QUOTE_DEBIT_TOO_SMALL(68)
Align the value with the Pair's limits fromGET /v1/spot/config. - Funds and account limits · state changed: no
INSUFFICIENT_FUNDS(3),RISK_LIMIT(55),MAX_OPEN_ORDERS_TOTAL(205),MAX_OPEN_ORDERS_PER_PAIR(306),POLICY_MAX_OPEN_ORDERS(34),POLICY_MAX_NOTIONAL(21)
Free funds or cancel orders first. - Market state · state changed: no
UNKNOWN_SYMBOL(4),PAIR_DISABLED(16),PAIR_NOT_LISTED_YET(50),PAIR_DELISTED(51),PAIR_CANCEL_ONLY(52),PAIR_POST_ONLY(53),PAIR_REDUCE_ONLY(54),MARKET_HALTED(56),ORDER_TYPE_NOT_ALLOWED_IN_AUCTION(274),POST_ONLY_NOT_ALLOWED_IN_AUCTION(275)
Wait for the Pair's status to change. - Market orders · state changed: no
MARKET_PRICE_UNAVAILABLE(37),EMPTY_BOOK(62),STALE_QUOTE(65),MARKET_QUOTE_STALE(200),MARKET_QUOTE_UNHEALTHY(201),PRICE_BAND_VIOLATION(60)
Retry later or send a limit order. - Permissions and policy · state changed: no
PERMISSION_DENIED(12),POLICY_MARKET_DENY(20),POLICY_TRADING_HALTED(22),POLICY_SPOT_TRADE_DENY(23),API_KEY_POLICY_REQUIRED(27),API_KEY_MARKET_DENY(29),ACCOUNT_ORDERS_SUSPENDED(263)
Check the key's policy and the account's permissions; do not retry unchanged. - Order identity · state changed: see the codes
CONFLICT_DUPLICATE_CLIENT_ORDER_ID(9),CONFLICT_IDEMPOTENCY_KEY_REUSE(36),ORDER_UNKNOWN(17),ORDER_ALREADY_TERMINAL(64),MODIFICATION_REQUIRES_REPLACE(35),QTY_AT_OR_BELOW_FILLED(76)QTY_AT_OR_BELOW_FILLEDended the order at its filled quantity; the others changed nothing. - Busy, retry shortly · state changed: no
UNAVAILABLE(10),OVERLOADED(67),PAIR_BACKLOGGED(207),ORDER_MODIFY_IN_PROGRESS(226),ORDER_PLACEMENT_PENDING(227),SETTLEMENT_BACKLOGGED(84),ACCOUNT_REPAIRING(300),FEE_SCHEDULE_UNAVAILABLE(220),POLICY_UNAVAILABLE(221)
Retry after a short backoff with jitter. - Rate limits · state changed: no
RATE_LIMIT_EXCEEDED(69),SYSTEM_RATE_LIMITED(225),RATE_LIMIT_POLICY_UNAVAILABLE(224)
See Rate limits. - Outcome unknown · state changed: maybe
ORDER_CREATE_OUTCOME_UNKNOWN(303),ORDER_CANCEL_OUTCOME_UNKNOWN(297),ORDER_MODIFY_OUTCOME_UNKNOWN(298)
Read the order before retrying; the connection closes with1013. - Server · state changed: not known
INTERNAL_ERROR(18),UPSTREAM_ERROR(14),GATEWAY_MISCONFIGURED(77)
Reconcile the affected orders, then report it to support with theseq,correlationId, andtsNs; retryingGATEWAY_MISCONFIGUREDdoes not help.
Some refusals are not command rejects. A post-only order that would cross, a fill-or-kill without
enough liquidity, or a market order the matching engine cannot fill may be admitted and then end as REJECTED or CANCELED in its OrderEvent, with rejectReason or cancelReason set.
Outcome unknown
An outcome-unknown code means Polyester sent the command onward but did not confirm the result in
time. The command may still apply. The server writes the reject, then closes the connection with 1013 and does not process any command you sent after it on that connection.
Before resending anything:
- Read the affected orders by
clientOrderIdororderId, or read all open orders. - Resolve every command that was unanswered when the connection closed.
- For a batch, resend the same
correlationIdand items: decided items return their original results and the rest are processed once.
UNAVAILABLE on its own means the command was not accepted. When an UNAVAILABLE reject is
followed by a 1013 close, treat the commands after it as unanswered.
Rate limits
SBE WebSocket commands spend from the same trading quotas as REST and ConnectRPC. Placement and
cancellation are separate pools per trading account, shared by every key and connection of that
account. A batch spends per admitted item. The pools, costs, and current limits are on Rate
limits. Read the limits that apply to
your account with GET /v1/trading/rate-limits (ConnectRPC GetTradingRateLimits).
| Command | Pool |
|---|---|
CreateOrder, ModifyOrder | TRADING_PLACE |
BatchCreateOrders, BatchReplaceOrders | TRADING_PLACE, per item |
CancelOrder, CancelAllOrders | TRADING_CANCEL |
BatchCancelOrders | TRADING_CANCEL, per item |
Ping, Subscribe | None |
A rate-limit rejection carries the quota details and the minimum retry delay in its rateLimit* fields; for any other rejection they are null or zero.
| Field | Meaning |
|---|---|
rateLimitWeight | Maximum weighted capacity of the exhausted quota |
rateLimitRemaining | Capacity left after the decision. Null (UINT64_MAX) when not rate-limit related |
rateLimitRetryAfterNs | Minimum delay in nanoseconds before retrying. 0 means no delay applies |
rateLimitPolicyVersion | Version of the quota policy used |
rateLimitOperation | The operation that was limited, such as CREATE_ORDER or BATCH_CANCEL_ORDERS |
rateLimitPolicyClass | TRADING_PLACE or TRADING_CANCEL |
rateLimitScope | ACCOUNT: the capacity belongs to the trading account |
rateLimitRefillModel | CONTINUOUS: capacity returns gradually, not at a fixed boundary |
In a batch, rate-limited items are rejected individually with RATE_LIMIT_EXCEEDED. The batch
acknowledgement then carries rateLimitWeight, rateLimitRemaining, rateLimitRetryAfterNs, and rateLimitPolicyVersion; they are null or zero when no item was rate-limited.
To retry, wait at least rateLimitRetryAfterNs plus a little jitter, keep idempotency identities
unchanged, and do not split a limited batch into many single commands.
Limits that are not your quota
| Code | Meaning | What to do |
|---|---|---|
OVERLOADED | Your account has too many order requests outstanding across all its connections, or the trading service is at capacity | Retry once earlier commands are answered |
SYSTEM_RATE_LIMITED | The venue-wide admission rate shared with other accounts is exhausted | Retry shortly with backoff |
RATE_LIMIT_POLICY_UNAVAILABLE | No usable rate-limit policy applies to the account right now | Retry later |
PAIR_BACKLOGGED | The Pair is busy with your account's earlier requests; nothing was reserved | Retry shortly |
OVERLOADED carries no rateLimit* details: it is not a quota.
Session and connection limits
Up to 16 concurrent sessions per API key and 64 per account are always accepted, and one IP address
can hold 200 open connections. Upgrades above these are refused with HTTP 429; see Upgrade
failures.
Commands on this interface do not count against the per-IP request limit of REST and ConnectRPC
order writes.
The first command of every connection must use seq 1, including after a reconnect. A client
that keeps its counter across connections is rejected until it restarts at 1.
The header's version is not the version your environment accepts, the blockLength does not
match the schema, or the frame has trailing bytes. Download the environment's schema again and
regenerate. The detail text names the cause, for example "unexpected SBE schema version".
A MARKET order must use IOC and leave priceTicks null. An encoder that leaves priceTicks at 0 sends a price. See Null values.