Kronos X Member API, Complete Code Reference

Revision 2.43, 21 October 2026 (Member API 3.86: the 2014 row naming an amendment or a cancellation of a GTD order at or past its expireTs, and the GTD_EXPIRED value stating that such an order never trades from that instant; revision 2.42 was 21 October 2026, Member API 3.85, with the 1001 row naming the WebSocket login challenge, the 1002 row naming the receive window refused rather than reduced, the 5 s forward bound, the record of signed writes and the start fence, the 2009 row naming the RFQ request and quote, and the retry matrix signing every retry afresh; revision 2.41 was 21 October 2026, Member API 3.84, with the 2013, 2017 and 5003 rows grown for the cancel-all that reads its filters strictly, DELETE /v1/orders and the WebSocket order.cancelAll with its side filter, and for DELETE /v1/orders/ with a trailing slash, an empty orderId; revision 2.40 was 20 October 2026, Member API 3.83, with the 2003 row naming the conditional orders, whose trigger price and limit price the band never checks and whose triggered limit child the collar never bounds, the 2019 row naming the ranges of the cursor fields and the sentence of a field out of range, the 3006 row naming the re-listing, the 5000 row naming the WebSocket ack of a write whose commit the venue did not confirm and the two venue-side faults a single WebSocket write still acks 2013, the 5001 row and the retry matrix naming a single write at a leader change, the 5030 row and the retry matrix naming the leader hint, the connections of a node that is not the leader and the clustered sandbox, the USER_REQUESTED value naming the cancel on disconnect, the member-wide cancel-all and the kill switch, and the REPAIRING state; revision 2.39 was 17 October 2026, Member API 3.79, with the 1003 and 5005 rows grown for the budget of contained engine faults, the 1003 row and the retry matrix naming its own refusal text, the 1003 and 5005 rows and the retry matrix letting the requests that can only reduce your risk pass the budget, and the 1001 close code row naming the second cause of venue restart; revision 2.38 was 12 October 2026, Member API 3.76, with the 5030 row and the 1001 close code row grown for the leader change on the WebSocket; revision 2.37 was 29 September 2026, Member API 3.74, with the 1003, 1004, 2002, 2013, 2014, 2017, 5000, 5001, 5005 and 5030 rows and the retry matrix grown for the batch amendment and cancellation routes; revision 2.36 was 28 September 2026, Member API 3.73, with the 5007 row added and the 1003, 5003 and 5004 rows grown; revision 2.35 was 21 September 2026, Member API 3.72, with the 2013 row gaining the whitespace refusal; revision 2.34 was 10 September 2026, with the 2049 row added 11 September 2026, Member API 3.70, and the 2028 row reworded in place 16 September 2026, Member API 3.71), covering Kronos X v2.0 "Pacifica". Every numeric code and every enumerated string value the API can return to a member, in one place. The numeric registry is a single venue-wide namespace: a code number is never reused or repurposed, and new codes are only ever added. Build parsers that treat unknown codes and unknown enum values as "new, not an error in your parser".

1. Where codes appear

SurfaceFieldNotes
REST response envelopecode (int), msg (string)code: 0 = the gateway accepted the request. Nonzero = rejected at the gateway; the HTTP status matches the table below. data.clOrdId is echoed on order-entry rejections when the body was parseable.
Engine order rejectiondata.status: "REJECTED" + data.rejectCode (int)Arrives INSIDE a 200 / code: 0 response: the gateway accepted the request, the engine rejected the order. Same numeric registry. Also on the WS order channel as an OrderRejected notification with rejectCode. Deliberate: the envelope reports that the request was processed and journaled, the payload is the order's state in the shape the reads serve; the WebSocket ack and the FIX report carry the same verdict where their protocols put verdicts (member reference section 6, "Where a rejection lands, per transport").
WebSocket op ackssuccess (bool), code (int), msgSame registry. code: 0 on success. On order.place the ack IS the verdict: an engine rejection acks success: false with the code, the registry wording and the order-state payload (status REJECTED, rejectCode) in data.
FIX ExecutionReport (35=8) and OrderCancelReject (35=9)tag 9010 (venue code), Text(58)Same registry. A rejected order is 150=8, 39=8 with the code in 9010; a gateway-level refusal carries OrderID(37)=0 (FIX rules of engagement section 4).
WebSocket close codesclose frame status codeSeparate small set (section 4: 1000, 1001, 4008, 4009), not part of the numeric registry.
Payload enumerationsvarious string fieldsClosed sets listed in section 5, with the documented exceptions treated as open.

Always branch on the NUMERIC code, never on msg text: messages may be reworded, codes never change meaning.

2. HTTP status usage

HTTPUsed for
200Accepted by the gateway (the engine may still reject inside the body, see above)
400Validation and risk rejections (most 2xxx and 3xxx codes)
4011001, 1002
4031005, 2034, 3002
4042014, 2024, 2025, 2031, 2032
4094001; ERP bridge externalRef conflicts
4291003, 1004
5005000, 5005
5035001, 5004, 5006, 5007, 5030

3. The numeric registry

3.1 Success

CodeNameMeaning
0OKRequest accepted. For order entry, still check data.status: a REJECTED order arrives with code: 0 and a rejectCode.

3.2 1xxx, authentication and throughput

CodeNameHTTPReturned whenClient action
1001AUTH_FAILED401Missing or unknown API key, bad HMAC signature, or (WS) failed auth op, a past expiresMs included. Also returned after a member is removed and its keys revoked. Since Member API revision 3.85 the WebSocket auth op also answers it when the frame carries no fourth arg, the pre-3.85 three-arg frame (msg auth failed: sign the nonce of this connection's challenge frame and send it as the fourth arg (Member API section 10.1)), or names a nonce other than its connection's challenge, a frame captured on another connection (msg auth failed: the nonce is not this connection's challenge); the connection stays open and unauthenticated.Fix credentials or signing. Verify your signer against the worked examples in the member reference section 3, including the comma-bearing query-string vector. A common cause on signed GETs with query strings: your HTTP library re-normalized percent-encoding after you signed (Python aiohttp/yarl re-encodes commas), so the wire query differs from the signed one; sign the exact bytes transmitted. Do not retry unchanged. On the WebSocket read the connection's first frame, its challenge, and sign "GET/ws/private" + expiresMs + nonce, sending the nonce as the fourth arg (member reference section 10.1); after a reconnect sign the new connection's nonce.
1002TIMESTAMP_OUT_OF_WINDOW401X-TIMESTAMP lies more than the recv window behind the venue clock (X-RECV-WINDOW, default 5000 ms, at most 60000; msg timestamp outside recv window). Since Member API revision 3.85 also: an X-TIMESTAMP more than the smaller of the window and 5000 ms AHEAD of the venue clock (msg timestamp ahead of the venue clock by more than the window allows (at most 5000 ms ahead)); an X-RECV-WINDOW that is not an integer from 1 to 60000, refused rather than reduced (msg X-RECV-WINDOW must be an integer from 1 to 60000 (milliseconds); a larger value is refused, not reduced); a signed write (any method but GET, POST /v1/margin/preview excepted) whose X-API-KEY and X-SIGNATURE the venue already accepted, kept for 60 seconds past its timestamp, so nothing of it runs (msg request already received: a signed write is accepted once, sign every request (a retry included) with a fresh X-TIMESTAMP); and a signed write stamped before the venue node began to accept writes, its start or its promotion to leader (msg request signed before this node began to accept writes: sign it again with a fresh X-TIMESTAMP); and a signed write stamped at or before the oldest write of the same member the node still records, once that one left the record, met only with a stamp more than 60 seconds old or when your own writes fill the record far above every published rate (msg request signed before the oldest one this node still records: sign it again with a fresh X-TIMESTAMP). The window is checked when the headers arrive and again once the whole body has arrived. The WebSocket auth op never answers this code: a past expiresMs is 1001.Sign the request again with a fresh X-TIMESTAMP and resend it (the same clOrdId on order entry and on RFQ requests and quotes, whose idempotency tells you whether the first send took effect); never resend identical bytes. Sync your clock with the venue's (NTP, GET /v1/time): a clock more than 5 s ahead is refused whatever the window. Send X-RECV-WINDOW as an integer from 1 to 60000 or not at all.
1003RATE_LIMITED429A per-member token bucket is empty, shared across all of the member's API keys (holding several keys does not multiply the budget). Two INDEPENDENT buckets: reads (default 6000/min) and the order budget (default 40000/min). Order placements, amendments and every entry of a placement or amendment batch consume the order budget, one unit each; cancels, the entries of a cancellation batch included, are never throttled. A placement batch (POST /v1/orders/batch / WS orders.batch) and, since Member API revision 3.74, an amendment batch (POST /v1/orders/batch/amend / WS orders.batchAmend, charged after the venue's engine-busy check) are charged one unit per entry up front, all or nothing: a denied batch consumes nothing, and the units of a batch whose entries are refused after the charge stay spent. A cancellation batch (POST /v1/orders/batch/cancel / WS orders.batchCancel) is never charged. Order-budget traffic does not consume a read token, so heavy order flow never exhausts your read allowance and vice versa. Both are full-capacity buckets: after a quiet period the entire minute's allowance is available at once. Where your rate-limit class publishes a per-SECOND ceiling on order entry (ordersPerSecBurst on GET /v1/account/parameters, 0 = none; the published ladder of section 4 of the Member API: STANDARD 1,000 orders/s on production, DMA 3,000, MM 5,000, the sandbox 0), a second bucket of that capacity binds beside the per-minute one and a burst above it answers this code with a retryAfterMs under one second even while the minute's allowance is unspent. Since Member API revision 3.70 the two public candle routes answer it from their own gate, and since Member API revision 3.73 a read of the history store answers it when more reads of yours of one route group are in flight on the node than it serves at once, or when the node's budget of these reads, which every member shares, is full: for these causes retryAfterMs is a SUGGESTED wait, not an exact refill, and a repeated 1003 there means your reads overlap, unless no other read of yours of the group was in flight, when it is the shared budget's. Since Member API revision 3.79 it also answers every request of yours that consumes the order budget once ten of your commands answered 5005 within 60 seconds, until the oldest of those ten is 60 seconds old: the refused request does nothing and consumes no order-budget unit, a request that consumes no order-budget unit (every cancellation among them) is never refused by it, and no other member is affected. A request that can only reduce your risk passes it too and still consumes its unit: a reduce-only order (reduceOnly true, FIX 9001=Y), a placement batch whose every entry is reduce-only, a lot close sent with reduceOnly true, and a barrier early close (the holder's close request, the writer's quote on it and the holder's accept of that quote; each passes only for your own contract, the read that tells them apart consumes one unit of your read budget, and while the venue sheds order entry, or when that read meets a full engine queue, it answers 5001 as below the budget while order-budget units remain); an amendment, and a placement batch with even one entry that is not reduce-only, are still refused. Such a refusal carries msg rate limit: repeated engine faults (5005) (FIX: Text(58) begins with it, before the wait), every other cause of this code keeps its text, and ten in 60 seconds is the published value, which production runs on every node.Sleep data.retryAfterMs, then retry with the same clOrdId (a denied batch: resend the same batch). The buckets refill continuously, so that value is the exact wait, typically a millisecond or two for the order bucket; for a denied batch it covers the full N-unit deficit. Assuming a fixed window instead costs up to 60 seconds of dead time. REST also sets Retry-After and X-RateLimit-Retry-After-Ms; the WebSocket ack carries data.retryAfterMs; FIX puts it in Text(58). A higher allowance is only ever a published class of the rate-limit ladder whose objective criteria you meet (Member API section 4: DMA, MM, or another class the venue publishes); ask venue operations for the class assignment. A member-specific number is only ever tighter than your class; your class and the values in force are account.rateLimits on GET /v1/account/parameters. For a history read, serialise your readers. A 1003 of a history read while no other read of yours of the group is in flight comes from the node's shared budget, which serialising cannot help: sleep the wait and back off if it repeats. After 5005 answers (the fault budget of Member API section 4) the wait can be up to 60 seconds: sleep it, and never resend the commands that answered 5005 unchanged.
1004OTR_BLOCKED429The RTS 9 order-to-trade regime block threshold is breached on the market whose ratio is breached (revision 2.34: the ratio is measured per member per market on the order-book markets, markets[].otr on GET /v1/account/parameters). Blocks NEW orders, placement batch entries (every entry counts as one order message on its market; a placement batch with any entry on a blocked market is refused as a whole and counts nothing), amendments and, since Member API revision 3.74, amendment batch entries on that market (an amendment batch answers this code as the ROW of each entry naming an order on a blocked market, counts nothing for it and runs its other entries; an entry counts as one order message on its order's market when the venue hands it to the matching engine); your other markets are unaffected; cancels always pass, a cancellation batch included (and count on the market they cancel on).Reduce your order-to-trade ratio on that market (trade more or send less there). The block clears as the market's sliding window recovers.
1005KEY_NOT_PERMITTED403The credential is READ_ONLY (drop copy): order entry, cancel, amend and configuration writes are refused on every transport, before the engine is reached. On FIX such a credential logs on as drop-copy regardless of tag 9003.Use your TRADE credential. Read-only keys exist so back-office, risk and surveillance systems provably cannot trade.

3.3 2xxx, order and request validation

CodeNameHTTPReturned whenClient action
2001UNKNOWN_SYMBOL400The symbol does not exist on this venue (or the market was deleted).Refresh GET /v1/instruments; never hard-code the instrument list.
2002TICK_LOT_MISALIGNED400A price or quantity the venue could READ as a decimal numeral but the instrument grid cannot admit: off the tick grid, not an exact multiple of the instrument's qtyStep (decimals at any depth included; the venue never rounds), zero, negative, out of range, or a required price missing or empty. A string that is not a decimal numeral at all (an exponent such as 1e-4, a blank, letters, a misplaced sign, a trailing point) is 2013 since Member API revision 3.60; before, it was 2002 too. Also the envelope-level reject of POST /v1/orders/batch / WS orders.batch and, since Member API revision 3.74, of POST /v1/orders/batch/amend / WS orders.batchAmend and POST /v1/orders/batch/cancel / WS orders.batchCancel for a malformed batch body, a member beside the batch's one array (orders, amends or cancels), or an entry count outside 1 to 50 (the msg says which), and the row of a batch amendment entry whose price or qty is a numeral off the order's grid.Align to tickSize/qtyStep from /v1/instruments. Quantities are decimal base-asset units; integer strings remain valid. For a batch envelope reject, fix the body shape or split the batch.
2003PRICE_OUTSIDE_BAND400A price outside the instrument's band around the mark (priceBandBps): a limit order's price at placement or on amend, an RFQ quote's price, or, at RFQ accept time, a quote the mark has since drifted away from (staleness re-check against the current mark). Never a conditional order's (member reference section 6, revision 3.83; kept by venue decision): neither the trigger price nor the limitPrice of a STOP_LIMIT or TAKE_PROFIT_LIMIT is checked against the band at placement, on amend or at activation, and its triggered limit child is not held to the market collar either, so it can rest outside the band and trade through the book up to its limitPrice.Reprice nearer the market; on an RFQ accept, take a fresh quote. A conditional order never draws this code: bound its limitPrice yourself.
2004UNSUPPORTED_ORDER_TYPE400Order type the venue does not run, including any trailing-stop request.Use the supported set: LIMIT, MARKET, STOP_MARKET, STOP_LIMIT, TAKE_PROFIT_MARKET, TAKE_PROFIT_LIMIT.
2005POST_ONLY_WOULD_CROSS400 (rejectCode)A POST_ONLY order would have traded on arrival.Reprice passively and resubmit.
2006FOK_UNFILLABLE400 (rejectCode)Historical registry entry: current builds cancel an unfillable FOK with cancelReason: "FOK_UNFILLABLE" rather than rejecting. Keep handling both.Treat as "nothing traded".
2007NO_ELIGIBLE_LIQUIDITY400MARKET order with no eligible opposing liquidity (empty book, or nothing your Market Segments configuration lets you trade with).Wait for liquidity or use a LIMIT order.
2008REDUCE_ONLY_VIOLATION400reduceOnly order that could increase the member NET position (wrong side, no position, or the reducible budget is already committed). Member-scoped, not per end client.Reduce size or drop the flag. NOT a per-client close tool: the budget is judged against your MEMBER net and never reads a client sub-position, so an end client closing its OWN position while your aggregate book leans the other way rejects here, and a perfectly netted member book (one client long 10 against another short 10 is a member net of exactly zero) refuses EVERY reduce-only order on that instrument, from either client, on either side. To close for one end client, send a PLAIN order (no reduceOnly) sized against that client's own row from GET /v1/positions/end-clients; only you know your client-level book. Same reason POST /v1/lots/{lotId}/close defaults reduceOnly to false. Keep the flag for shrinking your OWN house exposure, a risk desk flattening the member book during a margin call.
2009DUPLICATE_CLORDID400Two cases. ON AN ORDER: the clOrdId was used with a DIFFERENT payload while the venue still held the original reference. (An identical payload returns the original order with duplicate: true instead.) The venue holds a reference for 24 h, or until it has released it to stay inside its retention bound of the most recent 4,000,000 references venue-wide, whichever comes first; a reference whose order is still working or pending trigger is never released. Past that, the reference is simply unknown, so a resend places a new order rather than rejecting. On FIX the rejection is 150=8 with 2009 in 9010, and the identical-payload path is a 150=I restatement of the original order carrying 9015=Y. ON AN RFQ REQUEST OR QUOTE, since Member API revision 3.85: ANY reuse of a clOrdId, identical or not, on an RFQ request (POST /v1/rfq: a request, a close request, a yield contract offer) or a quote (POST /v1/rfq/{rfqId}/quotes), one namespace with your orders and swap takes: nothing is opened or replaced, there is no restatement of the original, and msg reads clOrdId already used: an RFQ request or quote is never restated, read GET /v1/rfq/mine or GET /v1/rfq/quotes/mine (from the matching engine's replay-contract line for that release).Generate unique references; retries must reuse the identical payload. On an RFQ request or quote, read GET /v1/rfq/mine or GET /v1/rfq/quotes/mine for what your first send opened; a new request or a re-quote carries a new clOrdId.
2010CLIENTUID_REQUIRED400Order without a clientUid from a member that is not market-maker house flow; also a barrier close request (closeContractId) whose clientUid is not the contract's holder-side client.Send the end-client reporting identifier on every order; on a close request omit clientUid or send the one the contract was opened under.
2011POSITION_LIMIT400The worst-case member net position after this order (your net position plus same-direction working orders plus this order) would exceed the market's position cap. On a market publishing maxPositionNotional the worst case is VALUED AT THE CURRENT MARK PRICE and compared against that notional cap (decimal settlement-currency string; notional denomination gives every market uniform dollar capacity). Where no notional cap is set, the legacy base-unit maxPositionQty applies unchanged. Risk-reducing flow is never blocked, and a position pushed above the cap by mark drift alone is never forced to reduce: the cap gates increases only.Reduce exposure or cancel same-direction working orders; the worst case counts them, not just fills. On a notional-capped market a mark move alone can take you to the cap, so size against the live mark.
2012TOO_MANY_OPEN_ORDERS400Member exceeds its max open orders limit: default 10,000 working plus untriggered conditional orders, MEMBER-wide across all instruments. Also the reject for the RFQ caps: 64 open RFQs per member, and 64 live quotes per request (one live quote per maker per request, so a re-quote replaces rather than adds).Cancel stale orders. Your live limit is on the member portal limits card and on GET /v1/account/parameters; a member-wide cap above the 10,000 default is only ever a published class assignment (Member API section 4), and a member-specific value is only ever tighter than your class.
2013INVALID_ORDER400Malformed field content (bad side/tif value, wrong type for a field on a hand-parsed surface such as the WebSocket single order ops and FIX, where a strictly parsed REST body and every batch entry answer 2017 instead, missing trigger on a conditional, trigger on a non-conditional, syntactically broken JSON body, and since Member API revision 3.60 a qty or price string that is not a decimal numeral at all: an exponent such as 1e-4, a blank, letters, a misplaced sign, a trailing point; a numeral the grid cannot admit stays 2002; and since Member API revision 3.72 a clOrdId, a clientUid or a Trader ID of the reg block (traderId, investmentDecisionId, executionDecisionId; on FIX ClOrdID(11), Account(1), the tags 9012, 9024 and 9025 and TargetOpenClOrdID(9028)) that BEGINS or ENDS with a whitespace character, on order entry, per batch entry, on the RFQ routes and as the path identifier of /v1/clients/{clientUid}/identity and /v1/trader-ids/{traderId}/identity: trim the value where you build it, the msg names the rule), a barrier CLOSE REQUEST (POST /v1/rfq with closeContractId, revision 3.44) that also carries side, qty or barrier (the venue derives all three from the contract; send only symbol and closeContractId plus the usual clOrdId, expiresInMs, reg), since Member API revision 3.74 the row of a batch amendment or cancellation entry that is not a JSON object, whose orderId is absent or below 1, that names both orderId and clOrdId or neither (a cancellation entry), whose clOrdId is empty, or that names an order an earlier entry of the same batch already names (order N is already named by entry k of this batch, k the earlier entry's index counted from 0: the first entry runs, the later one is not submitted), since Member API revision 3.84 a WebSocket order.cancelAll whose symbol or side is null or not a JSON string or is given twice, or whose args are given twice or are not exactly one object (none, null, an object, an empty array, two objects; msg names the member, for example symbol must be a string; nothing was cancelled, or order.cancelAll takes exactly one args object; nothing was cancelled; nothing is cancelled), or the per-order size cap. On a market publishing maxOrderNotional a single message is VALUED AT ITS EFFECTIVE PRICE and compared against that notional cap: priced orders (including the limit leg of conditionals) at their limit price, market orders and RFQ creation at the current mark, RFQ quotes at the quoted entry price for the request's full size, amends on the FULL amended quantity. reduceOnly is NOT exempt (a fat-finger guard applies to closes too; venue-initiated closes are). Where no notional cap is set, the base-unit maxOrderQty applies unchanged (a member-specific override can lower it, never raise it). ALSO, on every market and in both cap arms, an absolute size ceiling: one order's price x qty must stay within the venue's exact-money range (1000000000000000000 settlement-currency units), which is what lets the venue represent every trade, fee and position update exactly. It is not published per market and sits orders of magnitude above every maxOrderNotional in force; no tradable order approaches it. SEPARATELY, GET /v1/lots answers 2013 with an explanatory message when a fold exceeds one of its bounds: more than 100,000 fills for the (clientUid, symbol) scope, more than 20,000 funding settlements to attribute (about 18 years of an 8 hour grid, counted from the first fill the fold covers), or more than 5,000,000 attribution steps (settlements x lots open at each), which a client with both very long history and very many open lots can reach.Fix the request shape, or split the order: on a notional-capped market keep each message's price x qty under maxOrderNotional (closing a large position may take several orders, by design). On a lot fold, narrow the query with positionSide (a filtered fold does only that bucket's attribution work); past the settlements bound, or when one bucket alone exceeds the work bound, reconcile that client by positions and executions instead.
2014ORDER_NOT_FOUND404Cancel or amend target does not exist, is not yours, or is already terminal. Since Member API revision 3.74 also the ROW of a batch amendment or cancellation entry naming such an order, or a clOrdId naming no open order of yours: the venue submits nothing for it (a cancellation entry whose order filled between the venue's lookup and its cancel answers it from the matching engine). Since Member API revision 3.86 also an amendment (PUT /v1/orders/{orderId}, WebSocket order.amend, FIX 35=G, a batch amendment entry) or a cancellation (DELETE /v1/orders/{orderId}, by clOrdId, WebSocket order.cancel, FIX 35=F, a batch cancellation entry) of a GTD order at or past its expireTs: the order is expired (status EXPIRED, the GTD_EXPIRED case below), the answer the request receives once the venue's expiry sweep has run; a cancel-all expires such an order and counts it in canceled. The matching engine applies this from its replay-contract line for revision 3.86, the first command of a venue started on the production contract; venue operations announce the date on any environment where that line lies ahead.Treat as already-closed; reconcile via GET /v1/orders/{orderId} or the event stream.
2015SELF_TRADE_PREVENTED400 (rejectCode)Your configured STP policy is REJECT_TAKER and the incoming order would have matched your own same-clientUid order.Expected under that policy; handle like a reject.
2016SPOT_UNSUPPORTED400reduceOnly or a market-triggered conditional BUY on a spot market.Spot has no positions to reduce and prefunds worst case; drop the flag or use a limit conditional.
2017UNKNOWN_FIELD400STRICT order entry: the JSON body contains a field the venue does not define (for example a trailing parameter). Nothing is silently ignored. msg names the offending field. Also a value of the wrong JSON type in a strictly parsed body (PUT /v1/orders/{orderId}, POST /v1/orders and every batch entry, a number where the schema has a string, a string orderId): msg malformed request body. The member names of a batch entry are case-sensitive, so Qty for qty is an undefined field there. Since Member API revision 3.84 also any request body on DELETE /v1/orders (msg DELETE /v1/orders takes no request body: send clOrdId, symbol and side as query parameters; nothing was cancelled), and an args member of the WebSocket order.cancelAll other than symbol and side, its names case-sensitive (msg unknown field 'clientUid': order.cancelAll reads symbol and side only; nothing was cancelled); nothing is cancelled.Remove the field, or send the value as the schema types it. If you believed it did something, that assumption was wrong: read the order schema.
2018ASSERTION_MISMATCH400The optional leverage or quoteCcy assertion does not match this instrument and YOUR account's effective margin (imMultiplier applies).Read maxLeverage/leverageMode from /v1/instruments and imMultiplier from /v1/account; treat as a configuration alarm on your side.
2019INVALID_CURSOR400Malformed backfill cursor or unknown channel family on GET /v1/stream/events. A cursor is 30 ASCII digits: seq (19 digits, a signed 64-bit integer, 0 to 9223372036854775807), eventIndex (10 digits, a signed 32-bit integer, 0 to 2147483647: the 0-based position of an event among the events of one engine command, restarting at 0 for every seq) and leg (1 digit); member reference section 11.2. Since Member API revision 3.83 a well-formed 30-digit cursor whose seq or eventIndex field lies above its range answers this code with a msg naming the field and its range (afterCursor seq (characters 1 to 19) is out of range: it must be 0 to 9223372036854775807, afterCursor eventIndex (characters 20 to 29) is out of range: it must be 0 to 2147483647, the two joined by ; when both are); anything that is not 30 ASCII digits answers afterCursor must be 30 numeric characters, the text every malformed cursor answered before that revision.Re-fetch a cursor from GET /v1/stream/cursor. Store the 30-character strings the venue returns and pass them back unchanged; branch on the code, never on the msg.
2020RESERVED_CLORDID400clOrdId starts with the reserved venue namespace KX- (case-insensitive).Choose another prefix; KX- marks venue-generated references (KX-LQ-{orderId}, KX-ADL-{tradeId}).
2021TRADER_ID_REQUIRED400The order carries no reg.traderId, or one that is not a registered active Authorised User of your member. Enforcement is staged per member: a member with no registered Authorised Users is not gated at all, and once its first Authorised User is registered every order must carry a registered, active Trader ID. Identical on REST, WebSocket and FIX (venue tag 9012 on NewOrderSingle), because all three build the order through the same path. Margin previews are never gated on either transport, POST /v1/margin/preview and the WebSocket get.marginPreview op alike: a preview is a read, not an order entry. RFQ writes carry the same gate (POST /v1/rfq, the quote and the acceptance), and since revision 3.70 so do the member portal's RFQ request, quote and acceptance (the portal's error carries this sentence with code 2021, before 2024 and 2033; cancels stay ungated; the RFQ tab's Trader ID field applies to every RFQ write).Send the venue-issued Trader ID of the Authorised User entering the order in reg.traderId, or in tag 9012 on FIX. Venue operations issue the id when they register the user, typically in the form TR-{memberId}-{8 hex characters}. Treat it as an opaque string of up to 64 characters. Do not retry unchanged.
2022RFQ_MARKET_ONLY400Order entry names a market whose mode is RFQ. RFQ markets run no order book, so there is nothing for an order to rest on or match against; the reject happens at order admission on every transport.Read mode per symbol from GET /v1/instruments and trade the market through the RFQ flow instead: POST /v1/rfq, then accept a quote. RFQ entry (create, quote, accept, cancel) is REST only, with lifecycle pushes on the private WebSocket rfq channel; there is no FIX surface for any of it. Do not retry the order.
2023NOT_RFQ_MARKET400POST /v1/rfq names a market whose mode is ORDER_BOOK. RFQ requests only exist on RFQ-mode markets (quotes and accepts reference an existing rfqId, so the create is where this surfaces).Trade the symbol on its order book. mode on GET /v1/instruments tells you which flow each market runs.
2024RFQ_NOT_FOUND404The rfqId does not exist, is not yours to cancel or accept, is already closed (accepted, canceled, or the quoting window expired), or belongs to a member your Market Segments eligibility does not let you trade with: eligibility filtering answers not-found rather than forbidden, so nobody learns of requests they cannot quote. Also the answer to ANY member other than the contract's writer quoting a barrier CLOSE REQUEST (revision 3.44): a close request is visible to and quotable by its writer only, and everyone else is told it does not exist.Treat the RFQ as gone. Re-read GET /v1/rfq/open (as a maker) or GET /v1/rfq/mine (as a requester) and work from what is live; open a fresh RFQ if you still want the trade.
2025RFQ_QUOTE_NOT_FOUND404The quoteId is not a live quote on that RFQ: unknown, not yours (on a quote cancel), replaced by your own re-quote (one live quote per maker per RFQ), withdrawn, past its validity, or the quoting member can no longer trade with you (suspended, in liquidation, or eligibility changed between quote and accept).Requesters: pick another live quote from GET /v1/rfq/mine and accept before its expiryTs passes. Makers canceling: treat as already-withdrawn.
2026RFQ_SELF_TRADE400Your member quoted its own RFQ. Quotes are anonymous toward the requester, but the anonymity is presentational: both legs of an RFQ trade must be different members, and the check runs per member, not per API key or clientUid.Do not answer your own member's requests, from any desk or credential.
2027BARRIER_TERMS400Barrier (knock-out) terms are incoherent for the market and side. On create: barrier missing on a barrier market or supplied on a perp/spot RFQ, a level not strictly beyond the knock-out side of the current mark (BUY, a long holder, needs it below the mark; SELL, a short holder, above), an expiryTs not in the future, or (revision 3.43) a takeProfit not strictly on the profit side of the current mark (BUY needs it above the mark, SELL below). On quote: an entry price on the wrong side of the barrier (the barrier must stay strictly below a long holder's entry and strictly above a short holder's) or at or past the take profit (the take profit must stay strictly above a long holder's entry and strictly below a short holder's), or a contract whose implied maximum loss on either side, the entry-to-barrier distance (or the entry-to-take-profit distance) times qty times the contract value, would exceed the venue's exact-money range (1000000000000000000 settlement-currency units; not reachable at any tradable size, stated so the rule is total). On a close request (revision 3.44): the writer's price not strictly inside the contract's terms. STRICT take profit (revision 3.45): barrier.strictTakeProfit: true without a takeProfit, without an expiryTs, with an expiryTs more than 24 hours after the request, or on a market whose strictTakeProfitPremiumBps is 0 (strict take profit not offered), at create and again at accept. DATED CONTRACTS ONLY (revision 3.70, conditional): where the market publishes barrierExpiryRequired true on GET /v1/instruments, an OPENING request whose barrier.expiryTs is absent or 0 is refused at the gateway before anything is journaled, with the message this venue lists dated barrier contracts only: send barrier.expiryTs (REST envelope msg and the portal's error); close requests are untouched and the sandbox publishes false. MAXIMUM CONTRACT LIFE (revision 3.70, per market): where the market publishes maxContractLifeHours on GET /v1/instruments, an OPENING request whose barrier.expiryTs is absent, or later than the request time plus that many hours, is refused by the venue (a rule of the market, measured at the request); close requests are untouched and open contracts run to their terms.Re-read the mark, place the level strictly below both mark and entry for BUY and strictly above both for SELL, place any takeProfit on the opposite side, and omit barrier entirely on non-barrier RFQ markets. expiryTs and takeProfit are optional; without them the contract is open-ended and knock-out only, EXCEPT where barrierExpiryRequired reads true, in which case send an expiryTs in the future on every opening request, and EXCEPT where the market publishes maxContractLifeHours, in which case send an expiryTs at most that many hours after the request. For a strict take profit send both a takeProfit and an expiryTs within 24 hours, and read strictTakeProfitPremiumBps on GET /v1/instruments first (0 = not offered).
2028BELOW_MIN_NOTIONAL400The order or RFQ notional (price × qty) is below the instrument's minNotional (5 USD on every current listing, 100 USD on the barrier markets, a close request included: the request is valued at the contract's whole quantity at the current mark and the writer's close quote at its price, so a contract below the floor ends at its barrier, its take profit or its expiry and not by an early close; Member API revision 3.71). Priced orders are valued at the limit price (for conditional limit types, at the post-trigger limit price), market-type orders at the current mark. Amends re-check the FULL amended quantity at the effective price, so an amend can be rejected even when it only changes price. RFQs are checked at create (valued at the current mark) and on every quote (valued at the quoted entry price); accepts need no further check. Exempt from the floor: venue-initiated closes (liquidation, ADL), and reduceOnly orders and amends within your reducible position, so a position whose whole notional has fallen below the floor remains closable by you.Increase the quantity so price × qty reaches minNotional, or batch small client orders before submitting. To flatten a sub-floor residual position, submit a reduceOnly order of exactly the position size: reduce-only orders within your reducible position are exempt from the floor. A reduceOnly order LARGER than your reducible position still rejects with 2008, so do not oversize the close. Do not retry unchanged.
2029CLIENT_LIMIT400The venue's table of end-client identifiers is full, so this order or RFQ acceptance would have to register a clientUid the venue has NEVER seen. Orders and acceptances quoting an identifier the venue already knows are unaffected: only the first-ever use of a new identifier can hit this. The bound is 1,048,576 distinct identifiers venue-wide, against roughly 50,000 in use across all members, so it is not reachable at any realistic client count; it exists so that a generator of unique identifiers gone wrong is refused at admission rather than growing venue state without end. Nothing is retained on rejection and nothing is deleted to make room: identifiers carry lifetime realized PnL and funding per end client, so the table is capped, never pruned.Send the identifiers you actually use rather than a fresh one per order (a clientUid is the ultimate client's stable reference, not a message id: use clOrdId for per-message references). If your identifiers are correct and you still see this, contact venue operations. Do not retry unchanged.
2030CLIENT_IDENTITY_INVALID400An RTS 22 client identity submission (PUT /v1/clients/{clientUid}/identity, member reference section 6d) failed validation: type not NATURAL_PERSON or LEGAL_ENTITY, a required field missing for the client type, a field on the wrong client type (lei is LEGAL_ENTITY only; dateOfBirth, nationalId and nationalIdType are NATURAL_PERSON only), countryCode not ISO 3166-1 alpha-2, dateOfBirth not a valid YYYYMMDD date, identifierPriority outside 1 to 3, nationalId and nationalIdType not set together, a length bound breached, or an lei failing the ISO 17442 format or MOD 97-10 checksum, or, for a natural person without nationalId, a firstName or surname with no letter the ESMA CONCAT transliteration table can fold (a name written only in Greek or Cyrillic, for example: resubmit the names in transliterated Latin form or supply nationalId and nationalIdType; revision 3.49 of the Member API, section 6d). Also a path clientUid outside 1 to 64 characters. Since revision 3.53: in the ENFORCE stage of the RTS 22 Annex II rollout (production: in force from the venue's first day; sandbox: from Tuesday 2026-09-22, the WARN stage before that date reporting the same findings in the PUT echo warnings array instead), a nationalIdType the country does not designate, an identifierPriority that contradicts the Annex II table, a national identifier failing the country's format check, or a natural person without nationalId for a country whose row lists no CONCAT (EE, ES, IS, IT, MT, PL). The same code answers the trader identity route (PUT /v1/trader-ids/{traderId}/identity, section 6d): kind not PERSON or ALGO, a PERSON without branchCountry, an ALGO without a well-formed algoId or with person fields, or a path id outside A-Z a-z 0-9 . _ - (1 to 64). Since revision 3.70 (either client type): a positionHolderCategory outside the five MiFID II Article 58(4) values (INVESTMENT_FIRM_OR_CREDIT_INSTITUTION, INVESTMENT_FUND, OTHER_FINANCIAL_INSTITUTION, COMMERCIAL_UNDERTAKING, EMISSIONS_OPERATOR) or an ultimateParentLei failing the ISO 17442 format or checksum. Since the code audit of 2026-09-11 (revision 3.70, both rollout stages): a nationalId containing a control or formatting character, starting or ending with whitespace, or starting with =, +, - or @ (the value is filed verbatim as the Art 58 position holder identifier; a + or - inside the value is accepted).Fix the field the msg names and resubmit the whole record. Nothing was stored and the previous revision, if any, stands. Trading is unaffected: identity data is decoupled from order entry. Do not retry unchanged.
2031CLIENT_IDENTITY_NOT_FOUND404GET /v1/clients/{clientUid}/identity for a clientUid that has no identity record on file, or (revision 3.53) GET /v1/trader-ids/{traderId}/identity for a Trader ID with no identity on file. Since revision 3.70 also a natural person's record the venue pseudonymised at the retention floor (five years after the member reported the end of the relationship, member reference section 6d "Retention"): the identifying fields are gone from the record and its revisions and the GET answers exactly as for no record.Expected until the record is first submitted, and after a pseudonymisation. PUT the record, then re-read (a PUT after a pseudonymisation starts a new revision); GET /v1/clients/identity/missing lists every uncovered clientUid that traded on MiFIR-scope (perpetual and barrier) markets in the window.
2032UNKNOWN_LOT404POST /v1/lots/{lotId}/close (member reference section 6e) named a lotId that is not an OPEN lot of the given clientUid and symbol: never opened, already fully closed, consumed by a venue-side close (the lot view is clamped to the live sub-position), or belonging to a different client. Nothing was submitted.Re-read GET /v1/lots for that clientUid and symbol and act on the lots it actually returns. The view folds from the history store, so a fill acked a moment ago may not be reflected yet; poll the store watermark forward rather than retrying the same lotId unchanged.
2033TRADING_CAPACITY400Trading capacity enforcement (member reference section 6f) is at the ENFORCE stage for your member and the order, RFQ creation or RFQ quote violated it: reg.tradingCapacity absent, not exactly DEAL, MTCH or AOTC, not permitted by your licensing profile, DEAL with a clientUid that is neither absent nor your house reference, or MTCH/AOTC without a real end-client clientUid. On FIX also an OrderCapacity(528) value with no venue mapping (only P, G, R, A map) or one that contradicts tag 9021. Decided at the gateway; nothing reached the engine and nothing was journaled. Members at stage OFF or WARN never receive this code.Send the capacity your licensing profile permits with the matching clientUid shape, or contact venue operations if the permitted set looks wrong. Do not retry unchanged. Margin previews are never gated, so a preview cannot tell you whether the capacity gate will pass; the rules are static and published in section 6f.
2034NO_LICENSING_PROFILE403PRODUCTION only (ADR-15 fail-closed posture): your member has no licensing profile configured, so the venue refuses order acceptance on every surface (order entry, batch and lot close, order amend on REST, WS and FIX, RFQ create, quote and accept; on FIX a 35=G answers 35=9 with 9010=2034) until venue operations configure one. Profile configuration is a mandatory onboarding artifact sourced from the due diligence file. The sandbox runs fail-open and never answers this code.Contact venue operations to complete onboarding. Not retryable: nothing you send changes the answer until the profile exists.
2035CLOSE_CONTRACT400A barrier CLOSE REQUEST (POST /v1/rfq with closeContractId, member reference section 6b, revision 3.44) named a contract that is not an OPEN barrier contract YOU HOLD on symbol: never opened, already settled (knocked out, take profit, expired, torn up, finally settled or closed early), held by another member, written rather than held by you, on a different market, a zero or negative id, or a contract that already has a close request open (at most one at a time; a lazily expired one still counts until the venue's expiry sweep retires it, within a second). Also answered on POST /v1/rfq/{rfqId}/accept of a close request when the contract terminated between quote and accept (a belt: the termination cancels the request in the same command, so the accept normally finds no RFQ, 2024). Nothing was submitted or journaled on the create; nothing traded on the accept.Re-read GET /v1/barriers (role HOLDER, status OPEN) and use a contract id it lists; if a close request of yours is already open on it, quote against that one under GET /v1/rfq/mine or cancel it first. Do not retry unchanged.
2036SWAP_TERMS400A yield contract OFFER (POST /v1/rfq on a SWAP market, member reference section 6h, revision 3.51) names terms the market does not admit: rateBps outside 1 to the market's swapMaxRateBps, tenorDays outside swapMinTenorDays to swapMaxTenorDays, qty below the market's minimum take (minNotional, in asset units) or above maxOrderQty, minQty above qty, expiresInMs outside 60 s to 30 days, or a size whose principal plus reward would leave the venue's exact-money range. A qty or minQty that is zero or off the qtyStep grid is answered 2002 before any of this. msg is one fixed text listing the terms (it does not name the offending one). Nothing was posted.Read swapMinTenorDays, swapMaxTenorDays, swapMaxRateBps, minNotional and maxOrderQty from GET /v1/instruments and repost inside them.
2037SWAP_OFFER_ONLY400Swap markets have offers and takes, never quotes: POST /v1/rfq/{rfqId}/quotes against a swap offer, or POST /v1/rfq/{rfqId}/accept on a swap offer carrying a quoteId. Nothing was submitted.To provide liquidity on a swap market post your OWN offer; to take one, accept it with qty and no quoteId.
2038SWAP_SIZE400A swap TAKE (POST /v1/rfq/{rfqId}/accept with qty) named a size the offer does not admit: above the offer's remainingQty, above YOUR per-order cap (maxOrderQty), or below the offer's minimum take (the larger of the writer's minQty and the market's minNotional) without being the whole remainder. A qty that is zero or off the qtyStep grid is answered 2002 instead. Nothing traded.Re-read the offer on GET /v1/rfq/open (remainingQty, minQty) and take a size inside the rule; the whole remainder is always admissible.
2039QUOTE_OFF_MARKET400The accept of an OPENING barrier request (POST /v1/rfq/{rfqId}/accept on a BARRIER market, member reference section 6b, revision 3.55; in force on every environment) named a quote whose entry price lies more than the market's published band from the CURRENT mark (barrierGuard.entryBandBps on GET /v1/instruments, 50 bps unless the market sets its own; revision 3.70, the registry sentence names the field), or the mark itself is not live (no sequenced mark, or older than the market's staleness timeout, 60 s on the current barrier listings). A quote is priced against the mark the quoting member saw; executing it after the mark moved would transfer the move to one side, and a stale mark leaves nothing live to measure against. Nothing traded; the request stays open and the quote stays open. Never answered on an early-close accept (a close price is fenced by the contract's terms, 2027, not by the mark).Wait for fresh quotes (quoting members should refresh when the mark moves) or re-request; on a stale market wait for the mark to resume ticking. Do not retry unchanged.
2040TAKE_PROFIT_REACHED400The accept of an OPENING barrier request carries a takeProfit the CURRENT mark has already reached: BUY (long holder) with the mark at or above the level, SELL at or below (member reference section 6b, revision 3.55; in force on every environment since revision 3.70). The contract would terminate AT the take profit on the first tick after opening, an instant transfer from the writer off a quote priced before the move. Create and quote already fence the level on its own side of the mark and the entry (2027); this closes the drift window between quote and accept. Nothing traded; the request stays open and the quote stays open.Re-request with a takeProfit beyond the current mark, or accept a fresh quote after the mark settles. Do not retry unchanged.
2041TAKE_PROFIT_TOO_CLOSE400The accept of an OPENING barrier request carries a takeProfit closer to the accepted entry price than the market's barrierGuard.minTakeProfitBps of the entry (GET /v1/instruments; 10 unless the market sets its own; member reference section 6b, revision 3.55; in force on every environment since revision 3.70; a distance exactly at the floor passes). One tick of noise would pay the full take-profit settlement, so the venue refuses the near-immediate touch. The tick grid alone guarantees only one tick of distance, which is far less than 10 bps on a high-priced underlying. Nothing traded; the request stays open and the quote stays open.Re-request with the takeProfit at least the market's published floor away from the entry (0.1 percent of the entry unless the market sets its own). Do not retry unchanged.
2042BARRIER_TOO_CLOSE400The accept of an OPENING barrier request carries a barrier (knock-out level) closer to the accepted entry price than the market's barrierGuard.minBarrierBps of the entry (GET /v1/instruments; 10 unless the market sets its own; member reference section 6b, revision 3.55; in force on every environment since revision 3.70; a distance exactly at the floor passes): the loss-side mirror of 2041, a contract whose knock-out is near-immediate, forfeiting the holder's premium on the first tick of noise while paying entry fees on the full notional. Nothing traded; the request stays open and the quote stays open.Re-request with the barrier at least the market's published floor away from the entry (0.1 percent of the entry unless the market sets its own; 0.1 percent of the entry is also the smallest distance the venue considers a real contract, matching a 1000x effective leverage cap). Do not retry unchanged.
2043BARRIER_REACHED400The accept of an OPENING barrier request carries a barrier (knock-out level) the CURRENT mark has already reached or crossed: BUY (long holder) with the mark at or below the level, SELL at or above (member reference section 6b, revision 3.55; in force on every environment since revision 3.70). The loss-side mirror of 2040: the contract would knock out on the first tick after opening, forfeiting the holder's premium and paying entry fees on the full notional. Creation already fences the barrier on the knock-out side of the mark and the accept fences it against the entry (2027); this closes the drift window between quote and accept. Nothing traded; the request stays open and the quote stays open.Re-request with a barrier beyond the current mark, or accept a fresh quote after the mark settles. Do not retry unchanged.
2044PREMIUM_SHARE400A barrier quote (POST /v1/rfq/{rfqId}/quotes on an OPENING request) carries a premiumBps, your OWN premium share for THIS quote (member reference section 6b, revision 3.58), outside the allowed range: at least the market's effective share for the request's variant (normal: 10000 - knockOutRebateBps; strict: strictTakeProfitPremiumBps) and at most 10000. A writer can only make a contract MORE expensive than the market base, never cheaper. premiumBps on a close request or a non-barrier market is answered 2013 instead. Nothing was submitted.Re-quote with premiumBps inside [the market's effective share .. 10000] (read knockOutRebateBps / strictTakeProfitPremiumBps on GET /v1/instruments), or omit it for the market share.
2045CLORDID_COLLISION400Your clOrdId on an order or a swap take hashes to the same 64-bit value as a DIFFERENT clOrdId you still have live in the venue's idempotency window (member reference, revision 3.59; dormant until venue operations announce activation). The venue refuses the new command rather than displacing the stored reference, so a later retry of the earlier one still resolves correctly. Astronomically rare (a 64-bit hash collision within your own live references). Nothing was submitted or journaled.Re-send with a different clOrdId. The identical-payload retry path (2009) is unaffected: reuse the SAME clOrdId only for a true retry of the same command.
2046AUCTION_PHASE400An order type the market's trading phase does not admit (member reference section 6j, revision 3.67): an IOC, FOK, MARKET or conditional order on a SECURITY market during its opening or closing call or while it is closed. Limit GTC and GTD orders are admitted and rest for the uncross; cancels and amends work. Nothing was placed.Read tradingPhase on GET /v1/instruments (or the status.{symbol} frame); send a resting limit order, or wait for CONTINUOUS.
2049TOKEN_RESTRICTED400An order, an amend, an RFQ request, a quote or an accept on a SECURITY market whose DLT financial instrument is frozen on the Kronos X chain, or for a client (clientUid) whose custody wallet there is frozen by the venue registrar (member reference section 6i, revision 3.70): a measure with a ground and a case reference recorded on the ledger and served to venue operations only. Answered before anything is sequenced, on REST, the WebSocket ack and the FIX report (9010=2049) alike; the client's resting orders on SECURITY markets were cancelled when the wallet freeze was taken, a frozen instrument's markets are halted. Your other clients and markets are not touched; nothing was placed.Route no flow for that client or instrument until venue operations lift the freeze (the wallet reads status Frozen on GET /v1/chain/wallets, the instrument frozenBy on GET /chain/v1/tokens/{isin}); contact venue operations for the measure and its appeal route.

3.4 3xxx, risk and trading state

CodeNameHTTPReturned whenClient action
3001INSUFFICIENT_MARGIN400 (usually rejectCode)Perps: the pre-trade margin check fails (worst-case order margin, at the collar price for MARKET orders). Spot buys: free settlement cash cannot prefund the worst case. Also on withdrawals exceeding withdrawable equity.Reduce size, add cash, or free margin.
3002MEMBER_STATUS_FORBIDS403The member is SUSPENDED (blocked), in liquidation or default management (order placement, amends and withdrawals are all refused while riskStatus is LIQUIDATION or DEFAULTED; cancels stay accepted), or the action conflicts with a POST_ONLY / REDUCE_ONLY member session.Contact venue operations; watch riskStatus on /v1/account.
3003INSTRUMENT_HALTED400The instrument is HALTED (circuit breaker, administrative, or venue halt propagation). Halts can end: watch venueEvents for RESUME_TRADING.Pause flow on the symbol; resume on RESUME_TRADING.
3004INSUFFICIENT_ASSET400Spot SELL exceeding the free base-asset balance (balance minus open sell reservations). Also a swap TAKE (revision 3.51) whose principal plus taker fee exceeds what you can pay in the market's asset right now: your free balance in the asset, and on the USD swap no more than your available margin balance.Deposit the asset or cancel competing sells; on a swap take, reduce qty or free the asset.
3005NO_MARK_PRICE400The instrument has no sequenced mark price yet (newly listed, feed not live). Not a halt.Wait for the feed; poll /v1/mark-price.
3006INSTRUMENT_DELISTED400The instrument is DELISTED. Permanent for that listing, unlike 3003: after a re-listing (member reference section 2a; a tickSize or qtyStep change is never made in place) the same symbol can return as a new market with its own grid, under the symbol and isin the announcement names.Stop trading the symbol; flatten per venue instructions. Re-read GET /v1/instruments after the date a re-listing announces.
3007COUNTERPARTY_MARGIN400Your RFQ accept failed on the QUOTING member's side: at accept both parties are re-checked exactly like order admission, and the maker no longer passes (the margin probe at the trade price, its position limit, spot prefunding of its delivery leg, or, on barrier markets, the writer's tier margin or contract-lots cap). Your own failure on the same checks returns the usual code instead (3001, 3004, 2011). Nothing traded and no account was touched. On a swap TAKE (revision 3.51) it means the WRITER is no longer fit, or full: suspended, in reduce-only, in liquidation or default, blocked by an outstanding claim, or (revision 3.70) no longer holding the Market Maker Member designation, in which case the offer is WITHDRAWN in the same command (an rfq canceled frame to the writer); or at its per-member open-swap lots cap or its contract-count cap for your size, in which case the offer STAYS on the board (a smaller take may fit the lots cap, and a slot frees when one of the writer's contracts closes).Accept a different quote, or cancel and re-open the request. Resubmitting the same quoteId unchanged only succeeds if the maker's own state has improved in the meantime. On a swap market re-read the board: a withdrawn offer is gone, an offer at the writer's caps still lists and can be tried smaller or later.
3008SWAP_WRITER_BLOCKED400You posted a swap OFFER while a contract you WROTE carries an outstanding claim: a maturity (or final settlement) the venue could pay only in part from your balance in the asset (member reference section 6h). The block is derived from your live contracts, not a member flag: it lifts on its own the moment the venue's timer pays the last claim to zero from your later balance. Nothing was posted.Fund the asset (the venue retries the claim every second) and repost once GET /v1/swaps shows no DEFAULTED contract with you as WRITER.
3009MARKET_ACCESS400Your account may not open NEW risk on this market (member reference section 7, revision 3.61): the market requires admission (GET /v1/instruments accessMode ADMISSION) and you are not admitted, or venue operations set your access to it to DENIED (a measure with a rulebook ground, notified to you by mail with the appeal route). Reduce-only orders and barrier close requests stay admitted; open positions and contracts run to term, never a forced close. On an order, an RFQ, a quote, a swap offer or a take alike. Since member reference revision 3.70 the six swap markets are admission markets under the SWAP_COUNTERPARTY class of the Rules annex (member reference section 6h: the client category recorded for the member, the Swap Product Annex, conformance testing under Conformance Test Plan Section W; the admission covers both roles and is granted per market); every perpetual, spot and barrier market is open.Read GET /v1/account/parameters markets[].access. Reduce only, or apply for admission to the market under its published criteria (a DENIED measure appeals under Rules section 36; a refused admission goes to the complaints procedure of section 38). Since revision 3.70 the writer's quote on a barrier close request and the holder's acceptance of it stay admitted like the request itself (a close settles existing risk).
3010DEA_CLIENT_BLOCKED400The clientUid or reg.traderId of this reg.dea order (FIX 9026=Y) is an identifier venue operations STOPPED on your account (member reference section 4, revision 3.62): a measure against your provision of direct electronic access to ONE client (MiFID II Article 48(7), Rules sections 8 and 9), taken with a stated Rules ground and a case reference and notified to you by mail with the section 36 appeal route. Answered before anything is sequenced, on REST, the WebSocket ack and the FIX report alike. Your unmarked flow and the DEA flow of your other clients are not touched; the identifier's working orders are not cancelled by the venue.Cancel that identifier's working orders; route none of its flow until the stop is lifted; appeal under Rules section 36. Read GET /v1/account/parameters account.dea.stoppedIdentifiers.
3011DEA_FLOW_LIMIT400Your DEA-flow allowance for the calendar day (UTC) is reached: the count or the notional of reg.dea orders your published DEA class allows (revision 3.62). Only reg.dea orders count and only they are refused; the allowance resets at 00:00 UTC.Wait for the reset, or ask venue operations for a class whose criteria you meet. Read account.dea (limits, usedToday) on GET /v1/account/parameters.
3012LEDGER_FINALITY_PENDING400A movement OUT of a trading wallet on the Kronos X chain (POST /v1/chain/transfers, POST /v1/chain/unlock, a redemption) was refused because the chain has an unattested tail: the last proposed block has not yet reached the validator quorum (member reference section 6i, revision 3.66). Trading on SECURITY markets continues and fills stay irrevocable; only the exit from trading waits. Nothing was debited.Retry when GET /chain/v1/head shows unattestedTail: false (normally within seconds; venue operations are alerted the moment a block misses its quorum).
3013SWAP_WRITER_ROLE400You posted a swap OFFER but your account is not designated as a Market Maker Member (member reference section 6h, revision 3.70), or the offer carried a clientUid other than your house uid (a Market Maker Member writes on its own account only). The designation is granted under the Rules with a signed Market Maker Agreement and recorded on your onboarding record; a withdrawn designation is a Rules measure notified to you with the section 36 appeal route, and your standing offers are then withdrawn at the next take (3007). Answered before the market's terms are checked, once GET /v1/instruments swapWriterEligibility reads MARKET_MAKER on the market (while it reads ANY every member may write). Nothing was posted. Taking offers is unaffected.Take offers, or apply for the Market Maker Member designation under the Rules; a Market Maker Member re-sends the offer without clientUid or with its house uid.
3014FUNDING_CATCH_UP400This GRID perpetual's funding settlement is more than 60 s overdue and the venue is settling the missed anchors, each priced on the positions held when it lands (member reference section 7 "Catch-up fence", revision 3.70): an opening order, a non-reduce-only amend and an RFQ accept are refused until the catch-up lands; reduce-only flow stays admitted, and a conditional order whose trigger fires inside the window is canceled FUNDING_CATCH_UP instead of executed. Uniform per market, never per member. The venue lands the catch-up before it serves members after a restart and re-fires an overdue settle every second, so the window normally lasts seconds. Answered on REST, the WebSocket ack and FIX (9010=3014, the same text in Text(58)). Dormant on the sandbox until the decision batch epoch announced by venue operations, live on production from the first day.Wait for the next FUNDING_SETTLED event on the market (or GET /v1/funding/current nextFundingTs in the future), then resend; reduce-only orders need no wait.

3.5 4xxx, concurrency

CodeNameHTTPReturned whenClient action
4001VERSION_CONFLICT409Market Segments update with a stale version (someone changed the configuration between your read and write); since revision 3.63 the account configuration and each per-market layer (?symbol=) carry their own version.Re-read, reapply on top, resubmit.

3.6 5xxx, venue and system

CodeNameHTTPReturned whenClient action
5000INTERNAL_ERROR500An unhandled server-side error. Logged venue-side with the request route. Since Member API revision 3.74 also the ROW of a batch entry (placement, amendment or cancellation) whose outcome the venue could not confirm, msg outcome unknown: the venue could not confirm whether this entry took effect; read the order back on the leader before sending it again, inside a 200 / code: 0 answer whose other rows stand; before that revision such a fault answered the whole placement batch with this code (REST) or 2013 (WebSocket). Since Member API revision 3.83 also the WebSocket ack of a write op whose commit the venue did not confirm within its 10 second window on a clustered deployment, with msg internal error, the answer REST gives the same case with HTTP 500; before that revision the WebSocket acked it 2013 malformed request. The outcome of such a write is unknown: it may still execute. Two other venue-side faults still ack 2013 malformed request on a single WebSocket write op, where REST answers this code: a node whose cluster engine has stopped on a fault refuses the write before it enters the venue's log, and a write still waiting when a node's apply loop stops fails with its outcome unknown; a 2013 malformed request on a write you know to be well formed can be either, so reconcile it by clOrdId before you resubmit.Retry idempotent reads; for order entry reconcile by clOrdId before resubmitting. Report persistent 5000s to operations. On a batch row, read the order back on the leader (GET /v1/orders/{orderId}, or by clOrdId for a placement entry) before sending it again, and resend a placement entry only with the SAME clOrdId. After a write answered 5000 on REST or the WebSocket, read the order back on the leader by clOrdId, or send it again with the SAME clOrdId, before you decide (member reference section 10.7).
5001ENGINE_BUSY503The command queue is saturated. The command was NOT accepted. One exception on a clustered deployment (member reference section 10.7, Member API revision 3.83 states it): a SINGLE write, REST or WebSocket, answered 5001 while its node lost the leadership may already be in the venue's log and may still execute on the new leader at its original terms; a batch row's 5001 never is such a write. On a batch entry (Member API revision 3.74): that entry was not accepted, or was not submitted because the venue's intake refused an earlier entry of the same batch as it was submitted (msg not submitted: the venue's intake refused an earlier entry of this batch); its earlier neighbours may have taken effect, and on a clustered deployment, whose replicated intake can refuse an entry after the later ones were submitted, so may its later ones: read every row, never infer the rest of the batch from the first 5001. At the envelope of an amendment or cancellation batch also: the venue could not look the orders up, or eight of your cancellation batches already wait on the node; nothing was submitted.Retry with backoff and jitter, reusing the same clOrdId for order entry; after a batch, resend only the entries answered 5001. During a leader change, read a single write answered 5001 back on the leader by clOrdId before resending it, or resend it with the SAME clOrdId.
5002VENUE_HALTED400The whole venue is halted.Pause; watch venueEvents (scope: "VENUE") and GET /v1/status.
5003INVALID_PARAMETERS400Structural parameter errors on admin and backfill surfaces (for example both afterCursor and fromSeq on /v1/stream/events, or neither). msg names the parameter. On PUT /v1/account/parameters (revision 2.30) it is also the refusal of a value of your own that would loosen the rule in force or the venue's value for your account, a name that is not self-service, or a per-market value without symbol: msg is the sentence naming the rule. Since Member API revision 3.73, also a channels value on GET /v1/stream/events that names no family (an empty value, commas only): msg is channels must name at least one family. Since the same revision, also on every route a required query parameter that is absent, or a parameter value that does not parse as its documented type (an integer, true or false): msg names the parameter (symbol is required, limit must be a 32-bit integer, includeSkips must be true or false); before it such a request answered HTTP 400 with an empty body. Since Member API revision 3.84, also on DELETE /v1/orders a query parameter other than clOrdId, symbol and side (unknown parameter 'clientUid': DELETE /v1/orders reads clOrdId, symbol and side only; nothing was cancelled), one of them given twice (side is given more than once; nothing was cancelled), clOrdId with symbol or side (clOrdId names one order and cannot be combined with symbol or side; nothing was cancelled), and a side other than BUY or SELL (side must be BUY or SELL; nothing was cancelled), on that route and on the WebSocket order.cancelAll alike, and the empty orderId of DELETE /v1/orders/ with a trailing slash, with or without a query (orderId is empty: DELETE /v1/orders/ with a trailing slash names no order; send DELETE /v1/orders/{orderId} with the id, or DELETE /v1/orders without the slash to cancel all; nothing was cancelled); nothing is cancelled, where before such a request without clOrdId ran as a cancel of every open order the other filters matched (a repeated symbol excepted, which answered 2001), and one with clOrdId cancelled at most the order clOrdId named.Fix the call.
5004BACKFILL_UNAVAILABLE503This deployment runs without the durable event store, so /v1/stream/* and /v1/margin/calls cannot answer. On the event stream routes the same HTTP 503 also carries 5007, which is retried: branch on the code.Use snapshot reads plus dated history routes; confirm environment capabilities with operations.
5005COMMAND_FAILED500 (usually rejectCode)The venue accepted and durably recorded your command, then could not finish processing it. Rare, and always a venue-side fault rather than anything wrong with your request. On order entry it arrives like any other engine rejection, inside a 200 / code: 0 response as data.rejectCode, and the rest of data reports what the command DID achieve before it stopped: if it carries an orderId, that order exists and may be resting or partially filled, and any executions listed really happened. The venue stays up and keeps trading; the same code appears on the WS order channel and, on FIX, as 9010=5005. On FIX the reply is chosen by what the command actually did: nothing at all when the engine's own rejection, or a 2009 reused-reference verdict, is already the answer; an ExecType(150)=I restatement of the real order when the command left one standing (the order's own OrderID(37), OrdStatus(39), LeavesQty(151) and CumQty(14), never a fabricated Rejected); a 150=8 when the command created and left nothing; and on a cancel or replace an OrderCancelReject(35=9) only when the request did not take effect. Since Member API revision 3.74 a batch amendment or cancellation answers it per entry: the order's row with rejectCode 5005 when the entry took effect before the fault, a failure row with code 5005 when nothing took effect.Do NOT resubmit the identical request (a batch row carrying 5005 included: reconcile it before any resend and never resend it as it was): the engine is deterministic, so it fails the same way every time. Reconcile first: read GET /v1/orders/open and GET /v1/positions (or the orderId in the response) and act on what is actually there, cancelling the order if you did not want it. Then send a DIFFERENT request if you still need the position, and report the clOrdId plus the response timestamp to venue operations. Since Member API revision 3.79, ten 5005 answers of yours within 60 seconds turn every request of yours that consumes the order budget into 1003 until the oldest of them is 60 seconds old (Member API section 4); cancellations stay open, and so do the requests that can only reduce your risk (a reduce-only order, a batch of reduce-only entries only, a lot close sent reduce-only, a barrier early close).
5006LEDGER_UNAVAILABLE503A chain route was called while the chain host runs without its engine bridge: a venue-side configuration fault, never a member error. Nothing happened. A venue that does not run the Kronos X chain at all does not serve the /v1/chain/* and /chain/v1/* routes, which answer HTTP 404 there, not this code (member reference section 6i, revision 3.69 wording).Retry after a minute; if it persists, contact venue operations. On the venues that list SECURITY markets on GET /v1/instruments the routes are always served.
5007HISTORY_STORE_BUSY503A read served from the venue's history store (the event stream routes of member reference section 11 and the history routes of its section 4) did not complete within the venue's bound, a read of yours of the same group just exceeded it (the group is held), the store is catching up with the venue's writes, or the store did not answer. Nothing changed on your account. Since revision 3.73; before it the same failure answered 500 with 5000, and a read slower than the bound answers this code where it was served slowly before.Sleep data.retryAfterMs (also Retry-After), then retry the same read; back off exponentially if it repeats; after repeated 5007 on the same read, NARROW it (a smaller limit, a later cursor or from, no symbol); keep one read in flight per stream.
5030NOT_LEADER503Clustered deployments only: a request that is not a GET under /v1 reached a node that is not the leader, which answers it before the route runs (a read-only POST such as POST /v1/margin/preview included) and never forwards it. The command was NOT accepted and cannot reach the book later. The payload carries leaderId, the node that holds leadership, and leader, the member-facing https base URL venue operations configure for it, which on every venue deployment is the environment's published entry host (member reference section 1), never a node's own host name and never a WebSocket URL. While no leader is known, for example during an election, REST answers leaderId 0 with leader null and the WebSocket ack carries leaderId 0 and no leader. Reads and streams are served normally by any node. A node that is not the leader closes every HTTP connection after its answer, reads included (Connection: close on HTTP/1.1, GOAWAY on HTTP/2; over HTTP/2 it first reads the rest of a write's body, for at most 2 s), but does not close a WebSocket opened on it. A single-node deployment never emits it; the clustered sandbox at sandbox.mtf.perpetuals.net (member reference section 1a, from the date venue operations announce) emits it at a leader change (member reference section 10.7 states the rest since Member API revision 3.83). Since Member API revision 3.74 also the ack of the WebSocket ops orders.batchAmend and orders.batchCancel on a follower node, before anything is charged or counted: success false, msg NOT_LEADER, and leaderId and leader under data (on REST they sit at the top level of the body). Since Member API revision 3.76 also the ack, in the same shape and before anything is charged or counted, of every other WebSocket write op on a follower node: order.place, order.cancel, order.cancelAll, order.amend, orders.batch, marketSegments.set and session.cancelOnDisconnect, answered first, ahead of authentication and validation; the first six acked 5001 there before, and session.cancelOnDisconnect acked armed.Treat it as a redirect, never as a rejection. Accept leader only when it equals the entry host you configured for the environment, then send the request again there on a NEW connection, reusing the SAME clOrdId for order entry; if leader names any other host, send no credentials there, reconnect to your configured entry host and tell venue operations. If leader is null or absent, no leader is known yet: back off briefly and retry your entry host, again with the same clOrdId. On a WebSocket op, close the socket yourself at the first 5030 (the venue does not close it), reconnect to the entry host, auth, resubscribe, re-arm cancel-on-disconnect and send the op there. A cancel, cancel-all, amendment or cancellation batch answered 5030 did not take effect: send it again on the leader at once. This is a redirect, not a rate limit.

4. WebSocket close codes

Close codeNameMeaningReconnect guidance
1000NORMALYou closed the socket (standard RFC 6455 normal closure). The venue does NOT use 1000 for its own shutdown: a venue stop arrives as 1001.Reconnect normally if you still want the stream.
1001venue restartNormally the venue is stopping for a rollout or a restart (revision 3.45). One advisory control frame {"channel":"advisory","type":"advisory","advisory":"restart",...} precedes the close, guaranteed frames already released to the socket are written first, and new WebSocket upgrades answer HTTP 503 with Retry-After while the venue is stopping. Since Member API revision 3.79 the description also names the second cause: the venue sends the same advisory and close (FIX: Logout(35=5) with Text(58)="venue restart"), while it keeps running, to every session that may have missed a frame when a venue-side fault lost frames of one command or batch (the command itself executed); the venue keeps running, so new upgrades are not refused; the cursor backfill delivers every missed frame of the guaranteed families, and for the best-effort families and for rfq, barriers and venueEvents you re-read state (member reference section 10.8); the venue adds no other close code or reason for it. On a clustered deployment the same close with reason leader change, reconnect, after the advisory leaderChange (Member API revision 3.76), means the node you were connected to no longer leads; the venue stays up and new upgrades are not refused.Reconnect with backoff, auth again, resubscribe (subscriptions are not preserved), re-arm cancel-on-disconnect if you use it, then recover per the member reference section 10.8 (cursor backfill for the guaranteed families, state re-read for rfq and barriers). Not an error on your side.
4008SLOW_CONSUMERYou stopped reading and a guaranteed or reply queue overflowed. A terminal gap frame naming the backfillable families precedes the close.Wait at least 1000 ms. Reconnect, resubscribe, then backfill from the gap frame's cursor via GET /v1/stream/events. Fix your consumer speed.
4009IDLE_TIMEOUTNo inbound frame from you for 60 s. The server sends heartbeats; you must send SOMETHING (a ping every <= 30 s).Reconnect and add a keepalive ping. Nothing was dropped by an idle close.

5. Enumerated string values in payloads

5.1 Order lifecycle

status (order): NEW, PARTIALLY_FILLED, FILLED, CANCELED, EXPIRED, REJECTED, PENDING_TRIGGER. NEW is a working order with nothing filled; PARTIALLY_FILLED a working order with fills, whether it part filled on entry or its resting remainder was later consumed by an aggressor (Member API revision 3.60: the live state reads report the latter case as PARTIALLY_FILLED; before, they reported NEW with remainingQty below qty, and the sandbox keeps doing so until venue operations announce the activation of that rule).

cancelReason (closed set):

ValueEmitted when
USER_REQUESTEDYou canceled it: a cancel of yours on any transport, a member-wide cancel-all of yours (order.cancelAll, or DELETE /v1/orders without a symbol, from any session of yours), the member portal's kill switch, and the cancel on disconnect you armed (member reference section 10.5a), which reports this value by design because the armed protection is your own standing instruction; the value does not tell these apart (Member API revision 3.83 states it). ADMIN_CANCEL is reserved for cancels by venue operations.
IOC_REMAINDERIOC remainder after the sweep.
FOK_UNFILLABLEThe venue could not fill the whole FOK, so none of it traded. The collar is one reason the feasibility walk can refuse; it also refuses when completing the order would breach a venue limit the fill itself would have to respect.
GTD_EXPIREDGTD reached expireTs (surfaces as status EXPIRED). Since Member API revision 3.86 such an order never trades at or after expireTs, measured against the time the venue sequences each command: an order, an amendment, a cancellation, a trigger or a call auction's uncross that reaches it from that instant expires it, and the venue's expiry sweep, about once a second, expires one nothing reaches. The matching engine applies this from its replay-contract line for revision 3.86, the first command of a venue started on the production contract; venue operations announce the date on any environment where that line lies ahead.
STP_CANCELSelf-trade prevention canceled it under your policy.
LIQUIDATION_CANCELThe venue pulled it when a liquidation episode opened. VENUE-INITIATED.
ADMIN_CANCELVenue operations canceled it. VENUE-INITIATED.
INSTRUMENT_HALTCanceled by an instrument halt/delisting flow. VENUE-INITIATED.
MEMBER_SUSPENDEDCanceled because the member was suspended. VENUE-INITIATED.
REDUCE_ONLY_VIOLATIONA working reduce-only order was trimmed/canceled to respect the budget.
SPOT_UNFUNDEDA resting spot order lost its funding and was canceled at fill time.
POSITION_SIZE_LIMITSettling the fill would take the position beyond the venue's maximum representable size, so the order was canceled instead. Not reachable at any tradable size. VENUE-INITIATED.
MARKET_ACCESSThe venue cancelled the order on a DENIED market access decision for your account on that market, or on the market's switch to admission-only access while you hold no access decision (Member API revision 3.63; the value is named since 3.65, it read NONE before). Reduce-only flow stays admitted and open contracts run to term. VENUE-INITIATED.
FUNDING_CATCH_UPA conditional order whose trigger fired while the market's GRID funding catch-up was pending (the window in which order entry answers 3014, member reference section 7 "Catch-up fence", revision 3.70) was canceled instead of executed; a reduce-only conditional executes. The same value on the REST order read, the WebSocket order frame and FIX Text(58). VENUE-INITIATED.
POST_ONLY_WOULD_CROSSOn a scheduled SECURITY market (member reference section 6j, revision 3.70): a POST_ONLY order that rested through a call and was still crossing when the call ended without an uncross print for it (every candidate outside the collar, or the order paired only with your own or an ineligible order) is canceled when the market enters CONTINUOUS, because re-entering it would cross the book (the post-only rule for an order that was already acknowledged; a new order in the same case answers 2005). The same value on the REST order read, the WebSocket order frame and FIX Text(58). VENUE-INITIATED.

5.2 Executions

role: MAKER, TAKER. flags: NORMAL, LIQUIDATION, ADL, RFQ, BARRIER_CLOSE, SWAP, REVERSAL, AUCTION (revision 3.67: a call auction print on a SECURITY market, both sides at the maker rate; full list and priority below). SWAP (revision 3.51) marks a yield contract take (a take on a SWAP market): price is the offer's rateBps as a whole number, qty the taken asset quantity, the taker's side SELL (it delivers the asset), fees in the asset; it prints on the public trades feed too but is not price data (member reference section 6h). RFQ marks a privately negotiated trade on an RFQ-mode market: it appears on the public trades feed and in your executions like any other trade, but it does not update the last-trade print, fire conditional orders, or feed the circuit breaker, because a bilaterally negotiated price is not public book liquidity. refSource: MEMBER (your clOrdId), VENUE (venue-generated reference, KX-LQ-{orderId} or KX-ADL-{tradeId}). Key unsolicited-close handling on refSource, never on the shape of clOrdId.

5.3 venueEvents channel

type: SNAPSHOT, STOP_TRADING, RESUME_TRADING, LIQUIDATION, ADL, MARGIN_CALL, LIQUIDATION_COMPLETE, the advisory types STALE_MARK_WARNING and STALE_MARK_RECOVERED on both sockets, and on the private socket MEMBER_PARAMS (revision 3.61: a change of your own parameters, {scope, symbol, origin, set[], cleared[]}, the names only; re-read GET /v1/account/parameters) and, since Member API 3.70, the private advisory MARGIN_WATCH ({state ABOVE | CLEARED, ccy, utilisationPct, thresholdPct, reArmPct}, your margin utilisation crossing or clearing the venue's early-warning level; informational, not a margin call); treat the list as an open set.

MARGIN_WATCH state: ABOVE, CLEARED.

tradingState: TRADING, HALTED, REDUCE_ONLY, POST_ONLY, DELISTED.

STOP_TRADING reason: CIRCUIT_BREAKER, STALE_MARK_PRICE, DELISTING, ADMINISTRATIVE. RESUME_TRADING reason: ADMINISTRATIVE, CIRCUIT_BREAKER_EXPIRY, MARK_PRICE_RECOVERED.

MARGIN_CALL state: ACTIVE, CLEARED.

5.4 Delivery and recovery

Gap frame reason: SLOW_CONSUMER (terminal, close 4008 follows) or CONFLATED (market-data conflation, non-terminal). Gap frame delivery: GUARANTEED or BEST_EFFORT.

Backfill store.status: COMPLETE (level with the engine), CATCHING_UP (poll again with the returned cursor), REPAIRING (the store of the node that answered has a recorded hole: reads stall below it rather than skipping it; keep polling, raise an operational alert; it starts at every leader change of a clustered venue, no timeout ends it and the venue sets no maximum duration, it ends when the hole is re-folded from the venue's journal, and while it stands lagSeq counts from the start of the hole to the engine head; member reference section 11.3, Member API revision 3.83).

5.5 Account and reference data

riskStatus (account): NORMAL, MARGINCALL, LIQUIDATION, DEFAULTED.

Instrument status on GET /v1/status and /v1/instruments: ACTIVE, HALTED, REDUCEONLY, POSTONLYSESSION, DELISTED (legacy spellings; the venueEvents channel publishes the same facts as tradingState above).

leverageMode (instrument): FIXED (single open-ended tier, maxLeverage present) or TIERED (maxLeverage null).

kind (instrument): PERP, SPOT, SECURITY (a DLT financial instrument settled on the Kronos X chain, revision 3.66; behaves like SPOT), BARRIER (knock-out contracts, traded by RFQ only), SWAP (revision 3.51: writer-first fixed yield contracts in the market's baseAsset, offers and takes by RFQ only, no price, no mark, no margin; member reference section 6h).

mode (instrument): ORDER_BOOK (central limit order book) or RFQ (request-for-quote: no book, trade via POST /v1/rfq). Barrier markets are always RFQ, and so are swap markets. Read the mode per symbol from GET /v1/instruments; order entry on an RFQ market rejects 2022, and RFQ operations on an order-book market reject 2023.

Funding history skipReason (GET /v1/funding/history?includeSkips=true rows and the WS funding.{symbol} type: "skipped" frame, member reference revision 3.70): NO_POSITION_SNAPSHOT (no position snapshot was held when the LOCAL_DAILY window closed) or NO_MARK_SNAPSHOTS (no mark was recorded inside the VWAP window). An OPEN set: treat an unknown value as a new reason. Present, with skipped true, only on the rows includeSkips=true adds; the default list never carries either field and a settled row never carries skipped. The funding.{symbol} frame type set: rate, settlement, settlementDetail (LOCAL_DAILY only), skipped (LOCAL_DAILY only, revision 3.70).

Ledger kind (GET /v1/account/ledger and the wallet channel) gains BARRIERSETTLE: the realised P&L leg from the close of a barrier contract (knock-out, take profit, expiry, liquidation tear-up, final settlement or an early close by RFQ). Zero-sum between holder and writer; the entry fee legs, and on an early close the closing trade's fee legs, remain ordinary FEE entries. Revision 3.51 adds SWAPPRINCIPAL (a yield contract take: the taker's principal moving to the writer, refId = the contract id, ccy = the market's asset) and SWAPSETTLE (principal plus reward, or the part of it the writer could pay, moving from the writer to the taker at maturity, at a later cure of a claim, or at the final settlement of a delisted swap market; same refId and ccy); the take's fee legs are ordinary FEE entries in the asset with refId = the take's tradeId. Both zero-sum between the parties.

Swap contract status (GET /v1/swaps, the WS swaps channel; revision 3.51): OPEN (live, principal with the writer), DEFAULTED (live: settled short, the taker's claim outstanding, the writer blocked from new offers), MATURED (closed, paid in full at maturity), CURED (closed, the claim paid to zero by a later retry), FINAL_SETTLEMENT (closed, operator close-out of a delisted swap market at principal plus the pro rata reward). WS swaps frame type: opened, matured, default, cured, finalSettlement. Swap role (GET /v1/swaps, swaps and rfq accepted frames): WRITER, TAKER.

Trade flags (GET /v1/trades, GET /v1/executions, the WS trades and execution frames, the FIX trade tape 35=X, venue tag 9014): NORMAL, LIQUIDATION, ADL, RFQ, BARRIER_CLOSE (revision 3.44: the closing trade of an accepted barrier close request, ranking above RFQ), SWAP (revision 3.51: a yield contract take, ranking above RFQ), REVERSAL, AUCTION (revision 3.67: a call auction print on a SECURITY market, ranking below RFQ and above NORMAL). One value per trade, by priority: REVERSAL, ADL, LIQUIDATION, SWAP, BARRIER_CLOSE, RFQ, AUCTION, NORMAL.

Barrier terminationReason (GET /v1/barriers?status=CLOSED, the WS barriers channel): KNOCK_OUT, TAKE_PROFIT, EXPIRY, TEAR_UP, FINAL_SETTLEMENT, EARLY_CLOSE (revision 3.44: the holder's close request accepted at the writer's quoted price; WS frame type earlyClose).

ADL indicator adlQuintile: integer 1 to 5 (5 = first in line to be auto-deleveraged).

6. Retry matrix (summary)

CodesRetry?
1002, 1003, 1004, 5001, 5007Yes, with backoff (same clOrdId on order entry; a 5001 batch row: resend that entry alone, its neighbours may have taken effect). A single write answered 5001 during a leader change on a clustered deployment may still execute: reconcile it by clOrdId on the leader before resending it, or resend it with the SAME clOrdId (Member API revision 3.83). Every retry is SIGNED AGAIN with a fresh X-TIMESTAMP, never sent as the same bytes: since Member API revision 3.85 a signed write is accepted once, and a resend of identical bytes answers 1002 request already received. A 1002 naming X-RECV-WINDOW or a timestamp ahead is fixed first (the header or the clock). A 1003 whose msg is rate limit: repeated engine faults (5005) (Member API section 4): sleep retryAfterMs, up to 60 seconds, and never resend the commands that answered 5005 unchanged. Cancellations and the requests that can only reduce your risk (Member API section 4) are not refused by that budget.
5000Reads yes; order entry only after reconciling by clOrdId on the leader, a WebSocket write ack 5000 included (Member API revision 3.83); a batch row only after reading the order back on the leader.
5005No, never unchanged: a deterministic venue fails an identical request identically. Reconcile against what the response reports, then send a different request if you still need the position. A batch row carrying 5005 is reconciled before any resend and never resent as it was.
2046, 3003, 3005, 5002Not a retry matter: wait for the state change event (for 2046 the market's next tradingPhase on the status.{symbol} channel, or rest a GTC or GTD LIMIT order for the next call, section 6j of the member reference).
1001, 1005, 2001 to 2045, 3001, 3002, 3004, 3006, 3007, 3008, 3009, 3013, 5003, 5004No. Fix the cause first; 2009's identical-payload path is the deliberate retry mechanism. 2045 means a different live clOrdId of yours collides on its hash: re-send with a different clOrdId. 1005 and 5004 are capability facts about the credential or the deployment, so no amount of retrying changes them. 2024 and 2025 mean the RFQ or quote is gone: re-read /v1/rfq/mine or /v1/rfq/open and act on what is still live. 3007 is the quoting member's failure, not yours: accept a different quote rather than resubmitting the same one. 2031 clears once the identity record is PUT, not by resending the GET. 2032 means the lot is gone or was never open: re-read GET /v1/lots and act on what it returns. 2035 means the contract is not an open one you hold, or already has a close request: re-read GET /v1/barriers and GET /v1/rfq/mine. 2036 to 2038 are swap term and size errors: re-read the market on GET /v1/instruments and the offer on GET /v1/rfq/open. 2039, 2040 and 2043 clear only with fresh quotes or a moved mark, 2041 and 2042 only with wider levels on a new request: never by resubmitting the same accept. 3008 clears only when your last outstanding swap claim is paid: fund the asset and watch GET /v1/swaps. 3009 clears only with admission to the market or a lifted denial: read GET /v1/account/parameters.
3010No, not for that identifier while the stop stands (its unmarked flow, and every other identifier, trade on); appeal under Rules section 36.
3011After 00:00 UTC, when the day's DEA-flow allowance resets.
3014Yes, after the next FUNDING_SETTLED event on the market (or once GET /v1/funding/current nextFundingTs lies in the future), usually seconds; reduce-only orders are admitted meanwhile.
4001Yes, after re-reading the current version.
5030Yes, but as a redirect, not a backoff and never as a rejection: when leader equals the entry host you configured, send the request again there on a new connection with the same clOrdId (a cancel or an amendment at once); otherwise reconnect to your entry host and tell venue operations (Member API section 10.7).

---

*This document is generated from the venue's single code registry (ErrorCodes.cs) and the shipped payload builders. Revision history follows the member API reference changelog.*