Perpetuals Kronos X v2.0 “Pacifica” Member API

Trading rules

The venue's trading manual: what every order type does, exactly when it rests, trades, is rejected or is cancelled, how margin and fees are computed, and what the venue does to your orders without being asked. This page is normative about behaviour. The wire formats live in REST, WebSocket and FIX; every numeric code is listed in the code reference.

Trading model

You are the member. The venue's counterparty is your firm: it holds the trading account, the margin, the API credentials and the legal relationship. Your end clients are known to the venue only through clientUid, an opaque reporting identifier you choose. The venue holds no name, no KYC and no personal data for an end client and cannot resolve a clientUid to a person.

Every order carries exactly one clientUid. A fill affects exactly the sub-position of that clientUid. The venue never offsets one end client's open interest against another's and never aggregates two end clients' orders into a single execution. What it does do is compute all risk on your member net position.

ConceptScopeRead by the risk engine
Initial margin, maintenance margin, equityMember, per settlement currencyyes
The position cap (maxPositionNotional, or legacy maxPositionQty where no notional cap is set) and the open-order count limitMember, per instrumentyes
reduceOnly budgetMember net positionyes
ADL quintile and rankingMemberyes
Fee rates and fee tierMemberyes
Per-clientUid sub-position, cost basis, realized PnLEnd clientno
Per-end-client leverageNot modelled at allno

Sub-positions are exact, durable and reconcilable through GET /v1/positions/end-clients, but they are reporting objects. The risk engine never reads them. Three consequences follow directly and each one has bitten an integration.

DMA consequence. Two end clients of the same member can hold opposite positions in the same instrument, and those positions net to zero member exposure, so the venue charges no margin for the pair. They can also trade with each other. Self-trade prevention is scoped to the end client by default (stpScope = END_CLIENT): two of your orders with different clientUid values cross normally, both sides pay their applicable fees, and both sub-positions move. The venue treats this as legitimate agency flow, not a wash trade. If your firm requires strict member-wide prevention, request stpScope = MEMBER from venue operations before go-live.
reduceOnly consequence. The reduceOnly budget is judged against your member NET position and never against an end client's sub-position. So one end client's reduce-only order can be admitted purely because another end client holds the opposite exposure, and, in the other direction, a client closing its own position is refused with 2008 whenever your aggregate book leans the other way. It is a control on your house exposure, not a per-client one. Read reduceOnly semantics in full before you put reduceOnly behind a client-facing close button.

The third consequence is that per-end-client leverage limits are yours to enforce, covered under Margin, leverage and fees below.

Trading hours and planned maintenance

Every market other than a SECURITY market with an auction schedule (Member API section 6j) trades continuously, 24 hours a day, every calendar day of the year, weekends and public holidays included, with no daily open, close or auction on any market other than a SECURITY market with an auction block, whose calls are its daily open and close (tradingHours SCHEDULED, member reference section 6j); the underlying reference market of a tradfi perpetual keeps its own opening hours while the contract trades on. Trading in a market is interrupted only by a suspension, halt or removal under the Rulebook (including a venue-wide suspension), by the circuit breaker, or by the reduce-only and post-only sessions (Halts and suspensions below, and GET /v1/status); the trading state of every market is published at all times on GET /v1/status, GET /v1/instruments and the venueEvents channel, and every instrument row carries tradingHours, CONTINUOUS on every listing (open set). Funding settles on the schedule published per market whether or not the underlying reference market is open; daily allowances and daily flow statements are kept per UTC calendar day.

The venue operates no daily or weekly closure. The only scheduled interruption is the standard maintenance window, Saturday 02:00 to 06:00 UTC, published as a standing exception to the trading hours; maintenance inside it is announced at least 48 hours in advance on the Website and in the member portal, and a release that requires the venue to stop is announced on the Website at least five Business Days ahead, naming the date, the start time in UTC and the expected duration, placed outside funding and settlement times. Most releases are rolling and need no window; one that needs it is executed with the restart procedure of the WebSocket page (advisory frame, close 1001, 503 with Retry-After, FIX Logout, cursor backfill): resting orders, positions, standing offers and open contracts survive it, subscriptions and cancel-on-disconnect arming do not, and trading resumes without an opening auction. A scheduled closure outside the window is published on the Website in advance with the notice the Rulebook requires for a material amendment; a stop without notice remains possible under the Rulebook's provision on suspension in response to system disruptions.

Instrument mechanics

Read GET /v1/instruments at startup and cache it. Never hard-code any of these values: sandbox and production configurations differ, and most parameters are reconfigured in place. The grid is the exception: a tickSize or qtyStep change is never made in place but by a re-listing (below).

PropertyMeaningIf violated
tickSizePrice grid. Every price you send, including trigger.price and trigger.limitPrice, must be an exact multiple.2002
qtyStepQuantity grid, in decimal base-asset units. Every qty must be an exact multiple and strictly positive; integer strings remain valid.2002
minQtySmallest accepted quantity. Equals qtyStep on every current listing.2002
minNotionalSmallest accepted order value, price x qty (5 USD on current listings, 100 USD on the barrier markets since revision 3.71, where it also applies to a close request at the contract's whole quantity). Priced orders valued at the limit price, market orders at the current mark; amends re-check the full amended quantity; RFQ creates valued at the mark, quotes at the quoted entry. Exempt: venue-initiated closes (liquidation, ADL) and reduceOnly orders within your reducible position, so a sub-floor residual position stays closable with a reduce-only order of exactly the position size.2028
priceBandBpsMaximum distance from the last sequenced mark for a resting limit price.2003
marketMaxSlippageBpsProtection collar for market orders and market-type triggers.see MARKET below
maxOrderNotionalPer-order size cap in settlement-currency notional (decimal string; absent or null where not set). One single message's price x qty at its effective price: 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 re-checked on the FULL amended quantity. A fat-finger guard on a single message, so reduceOnly orders are deliberately NOT exempt (closing a large position may take several orders); venue-initiated closes (liquidation, ADL) are exempt. Takes precedence over maxOrderQty when set.2013
maxOrderQtyLegacy per-order size cap, in base units. Applies only where the market publishes no maxOrderNotional; informational otherwise. A member-specific override can lower it further, never raise it.2013
maxPositionNotionalPosition cap in settlement-currency notional (decimal string; absent or null where not set). The worst-case member net position, checked as if every risk-increasing order filled, is valued at the CURRENT mark price and must not exceed it. Notional denomination gives every market the same dollar capacity, so smaller markets no longer reach their cap first in a correlated move. 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. Takes precedence over maxPositionQty when set.2011
maxPositionQtyLegacy base-unit position cap, same worst-case shape. Applies only where the market publishes no maxPositionNotional; informational otherwise.2011
riskTiersMarginal margin schedule by notional.n/a
maxLeverage, leverageModeFIXED with a value when the instrument runs a single open-ended tier, otherwise TIERED and maxLeverage is null.n/a
fundingIntervalHours, fundingThe period one settlement covers: 8 on the crypto perps (funding.schedule GRID, fixed UTC anchors), 24 on the daily-settled equity index, gold, oil and FX perps, and since revision 3.75 on the sandbox silver and the USD/JPY quanto (funding.schedule LOCAL_DAILY: positions and index captured at a local snapshot time, one mark per minute over a local window, the mean settled against the index at the window end, applied to the snapshot positions). Zero, and no funding block, on spot and barrier markets, which never fund. See the REST reference, Funding.n/a
tradingHoursCONTINUOUS on every listing without an auction schedule: no daily open, close or auction; SCHEDULED on a SECURITY market with an auction schedule (its hours are the auction block of the row, its phase in force tradingPhase); interruptions are the suspension, halt or removal, the circuit breaker and the reduce-only and post-only sessions (Trading hours and planned maintenance above, Halts and suspensions below). Open set.n/a

A grid change is a re-listing (revision 3.83). Every resting order and open position is held on the market's grid, so the venue's listing controls refuse an in-place change of tickSize or qtyStep on every market kind. A re-listing is announced in writing in advance (the market, the new values, the date). On the date the market is delisted (STOP_TRADING with reason DELISTING, every working and pending-trigger order cancelled with INSTRUMENT_HALT, 3006 from then on, reduce-only orders included, so close what you do not want final-settled before the date), open positions are final-settled at one close-out price, open barrier contracts within their terms, and the market is listed again with the new values and an empty book under the symbol and isin the announcement names. A resting order is never kept at the old granularity, moved onto the new grid or rounded. Nothing on the wire announces a re-listing before the date and no member surface serves an instrument id: key on the symbol and re-read the instruments after the announced date. minNotional is not part of the grid and may change in place.

Two rejects sit alongside the instrument grid and are frequently confused. 3003 means the instrument is halted: temporary, worth retrying. 3006 means delisted: permanent for that listing, stop retrying (a re-listing brings the symbol back as a new market). 3005 means the instrument has no sequenced mark price yet, which is neither of those; the market is open but has no priced basis for margin or bands, so wait for the feed.

Decimal strings everywhere. Every price, quantity, rate and money value on every transport is an exact decimal string ("65000.5", never 65000.5). Parse into a decimal type. The engine itself does all arithmetic in exact integers on the price and quantity grids, so a value that round-trips through a float will eventually disagree with the venue by one micro unit and become a reconciliation break.

Contract sizing: qtyStep, minQty and minNotional (reject 2028)

Quantities are decimal base-asset units. On BTC-USD-PERP, "qty": "0.0014" is 0.0014 BTC; prices are quoted per base unit, so the notional of an order is exactly price x qty. Worked example: buy 0.0014 BTC at 74000 is a 103.60 USD notional. Keep every quantity on the market's qtyStep grid (0.0001 on BTC-USD-PERP, BTC-USD and BTC-USD-KO, 0.001 on ETH-USD-PERP, ETH-USD and ETH-USD-KO, 0.01 on SOL-USD-PERP, SOL-USD and SOL-USD-KO, 0.001 on BNB-USD-PERP, BNB-USD and BNB-USD-KO, 1 on XRP-USD-PERP, XRP-USD and XRP-USD-KO on the current listings: the spot markets, revision 3.50, and the barrier markets, revision 3.71, share the grid of their perpetual, so the tradfi knock-out markets read 0.001 on SP500, NDX100 and XAU, 0.01 on WTI and BRENT and 1 on EUR, GBP and JPY; since revision 3.75 the sandbox lists HYPE, DOGE, ZEC, NEAR, TAO, US500, US100, XAG and USDJPY, each perpetual with its knock-out market, at 0.001 on ZEC, US500 and US100, 0.01 on HYPE, TAO, XAG and USDJPY and 1 on DOGE and NEAR, USDJPY being a quanto whose price is the USD/JPY rate and whose one unit pays 1 USD per 1.000 of it at that fixed rate) and keep price x qty at or above minNotional (5 USD on every current listing except the barrier markets, where it is 100 USD since revision 3.71 and applies to a close request as well; reject 2028 below it). Integer quantity strings remain valid; read the live values from GET /v1/instruments, never this page.

Order types

Every order needs symbol, side, type, tif, qty, clientUid and a clOrdId you generate (36 characters maximum, unique per member per 24 hours). Order entry is strict: an unknown JSON field is rejected with 2017, never ignored. This is deliberate. A silently discarded displayQty or postOnly would let you believe a constraint applied that never did.

The KX- prefix is reserved. A clOrdId beginning KX- is rejected with 2020, because the venue uses that namespace for its own liquidation and ADL references. The two namespaces therefore cannot collide, which is what makes refSource keying safe.

LIMIT

A price you will not cross. It trades immediately against everything eligible at or better than your price, then the remainder rests.

{
  "symbol": "BTC-USD-PERP",
  "side": "BUY",
  "type": "LIMIT",
  "tif": "GTC",
  "price": "65000",
  "qty": "2",
  "clOrdId": "a1f3c9d24b7e4f10",
  "clientUid": "CLIENT-A"
}

MARKET

You send no price. The venue computes a protection collar from the best eligible opposing price and marketMaxSlippageBps, and the order then behaves exactly like a limit order at the collar price. It will never print worse than the collar, which is what protects you in a thin or gapping book.

{
  "symbol": "BTC-USD-PERP",
  "side": "BUY",
  "type": "MARKET",
  "tif": "IOC",
  "qty": "1",
  "clOrdId": "m7b2e4a1c8d09f36",
  "clientUid": "CLIENT-B"
}

With a best eligible offer of "65000" and marketMaxSlippageBps of 50, the collar is 65000 + floor(65000 x 50 / 10000) = "65325". Everything at or below "65325" is available to you; anything above it is not, and the unfilled remainder cancels.

Margin is checked AT the collar price, not at the touch. The pre-trade margin probe values the order as if it rested at "65325", because in the worst case that is where it prints. A market buy therefore needs measurably more free margin than the top of book suggests, and a size that looks affordable against the touch can be rejected with 3001. Size against the collar, or call POST /v1/margin/preview first.

STOP_MARKET and STOP_LIMIT

Conditional orders. They are invisible to the book and consume no queue position until they trigger; their status is PENDING_TRIGGER throughout. On trigger, STOP_MARKET becomes a market order (collar computed at that moment, from the book as it then is) and STOP_LIMIT becomes a limit order at trigger.limitPrice.

{
  "symbol": "BTC-USD-PERP",
  "side": "SELL",
  "type": "STOP_LIMIT",
  "tif": "GTC",
  "qty": "1",
  "clOrdId": "s4e8a0c7b1d25f93",
  "clientUid": "CLIENT-A",
  "trigger": {
    "source": "MARK",
    "price": "60000",
    "direction": "AT_OR_BELOW",
    "limitPrice": "59900"
  }
}
trigger.sourceWatchesUse it for
LASTThe last trade print on this instrument.Execution-referenced logic where you specifically want a print to arm the order.
MARKThe venue mark price.Stop losses. The mark is the same price that drives your margin and your liquidation.
INDEXThe external index.Hedging against the underlying rather than against this venue's book.

Prefer MARK for protective stops. A single small print at a bad price moves LAST and can arm your stop into a book that has not actually moved; the mark is constructed to resist exactly that. The stronger reason is consistency: the venue liquidates you on the mark, so a stop referenced to the mark measures the same thing your risk does. A LAST-referenced stop can sit untriggered while the mark walks you into a margin call.

TAKE_PROFIT_MARKET and TAKE_PROFIT_LIMIT

Mechanically identical to the stop family: same trigger block, same sources, same directions, same activation path. The distinct type name documents intent (the trigger is conventionally on the profitable side) and is preserved on every execution record and regulatory extract, which is why you should use it rather than expressing a take-profit as a stop.

{
  "symbol": "ETH-USD-PERP",
  "side": "SELL",
  "type": "TAKE_PROFIT_MARKET",
  "tif": "IOC",
  "qty": "10",
  "reduceOnly": true,
  "clOrdId": "t9c1b6d38e0a4f27",
  "clientUid": "CLIENT-C",
  "trigger": {
    "source": "MARK",
    "price": "4200",
    "direction": "AT_OR_ABOVE"
  }
}

Time in force

TIFBehaviourTerminal reason
GTCRests until filled or cancelled.USER_REQUESTED
IOCTrades what it can immediately against eligible liquidity; the remainder cancels.IOC_REMAINDER
FOKAll or nothing, immediately. If the full quantity cannot trade, nothing trades.FOK_UNFILLABLE
POST_ONLYMust rest. If it would trade on arrival it is rejected with 2005 and nothing happens.reject, no order created
GTDRests until expireTs (Unix ms, must be in the future), then expires. It never trades at or after expireTs (Member API revision 3.86), measured against the time the venue sequences each command: an order, an amendment or a cancellation (each answered 2014), 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.GTD_EXPIRED, status EXPIRED

The FOK feasibility test is not a naive depth sum. It simulates the walk the engine would actually perform, honouring counterparty eligibility, your STP policy's stopping behaviour, the execution-time reduce-only cap on each maker, the funding of BOTH sides on spot, and the venue's exact-money range on a perpetual. That is what makes all-or-none exact: the venue never cancels a FOK that could have filled, and never fills one partially.

Two consequences for your cancel-reason handling, neither reachable at any tradable size. A perpetual FOK whose settlement would take a position past the venue's exact-money range now cancels whole with FOK_UNFILLABLE and no executions, where it used to fill what fitted and then cancel with POSITION_SIZE_LIMIT. A conditional spot FOK whose base asset left the account between acceptance and trigger now cancels whole with FOK_UNFILLABLE and delivers nothing, where it used to deliver what was still funded and then cancel with SPOT_UNFUNDED. Both of those reasons are unchanged on every other order type, where they still arrive as venue-initiated cancels: it is the FOK contract, not the guard, that changed.

MARKET plus FOK. Fully supported and all-or-none against the liquidity inside the collar, not against the whole book. Expect either a complete fill set or a single cancel with FOK_UNFILLABLE, never a partial. This is the safest way to express "fill my whole size now at a bounded price or not at all", and it is the combination to use in a hedging leg where a partial fill leaves you with unwanted exposure.
POST_ONLY counts your own resting orders. The would-cross test that produces 2005 does not exempt your own book, regardless of clientUid. A post-only order that would meet another of your own resting orders is rejected rather than being routed into STP. This is conservative on purpose: it keeps post-only rejection independent of your STP configuration, so the same order behaves the same way whichever policy you run.

What the venue does not offer

Stated plainly, so you do not build against a feature that is not there.

No iceberg or reserve orders

There is no hidden-quantity order type. A displayQty field is rejected with 2017 as an unknown field, not silently ignored, so a client that assumes icebergs will fail loudly on its first order rather than quietly showing full size.

The correct client-side substitute is order slicing: rest a child of your display size and submit the next child on each fill. Four rules make it work:

No trailing stops

Any trailing parameter is rejected, 2004 if it reaches the type check and 2017 as a stray field. Implement trailing on your side: watch the mark and amend or replace your stop. The reason this is not a venue feature is determinism. A venue-side trailing stop is a hidden order whose resting price depends on a continuous price history rather than on the command sequence, and the venue's core guarantee is that the same commands replayed produce the same state byte for byte, which is what makes every dispute answerable.

No pegged orders, no auctions

There are no pegged or discretionary order types and no opening, closing or intraday auctions in this release. The book is continuous from the moment an instrument is live. There is no good-till-crossing session. Halts are exactly that: order entry rejects with 3003 and resting orders remain in place, with no auction to reopen the market.

reduceOnly semantics

reduceOnly is a perp-only flag that refuses to increase your position. It is checked twice.

At admission. The order is rejected with 2008 unless your member net position in that instrument is non-zero, your side is the reducing side (sell against a long, buy against a short), and the sum of your already-pending reduce-only quantity on that side plus this order's quantity does not exceed the absolute net. Untriggered conditionals count against the same budget, so a stack of protective stops cannot silently over-commit.

At execution. A resting reduce-only order fills at most the maker's reducible quantity at that instant. If the position has already gone flat, the order is cancelled with REDUCE_ONLY_VIOLATION; if it has shrunk, the fill is trimmed to what remains reducible. This second check exists because the position can move between admission and fill through another of your orders, through funding or through a venue-initiated close. Independently, when your member position shrinks the venue trims your reduce-only orders, resting ones and untriggered conditional ones alike, newest first, or cancels them with REDUCE_ONLY_VIOLATION; a trim arrives unsolicited as OrderAmended (FIX 150=5).

reduceOnly is member-scoped. It is not a per-end-client control. The budget is measured against your member NET position in the instrument. The admission check never reads an end client's sub-position, because no risk logic at this venue reads sub-positions at all. The clientUid on the order selects which sub-position the fills land in; it has no bearing whatever on whether the order is admitted. If you have wired reduceOnly into a client-facing close, it will refuse closes your client is entitled to make.

What the flag is actually for. It is a venue-enforced guarantee that an order can only SHRINK your member's own house exposure, checked by the engine rather than trusted to your system. That is what you want when a risk desk is flattening the member book during a margin call: every order it sends is provably incapable of adding risk, whatever else is in flight, and the venue trims or cancels it as the position shrinks under it.

Closing an end client's position: send a plain order. Omit reduceOnly and gate the order on that client's own position, which you read from GET /v1/positions/end-clients. Only you know your client-level book, so only you can decide that a given order reduces a given client. A plain order carries no member-net precondition and therefore cannot be refused with 2008; it still passes the ordinary gates, margin and the position cap included, but the position cap never blocks risk-reducing flow. This is exactly why POST /v1/lots/{lotId}/close defaults reduceOnly to false. Keep reduceOnly for house-level risk reduction, where its guarantee is the point.

One useful property: reduce-only orders consume no order margin, because by construction they cannot increase exposure.

Matching

Price-time priority. Best price first; at equal price, earliest accepted first. Acceptance time is the sequencer's, not your clock's, and it is fixed at acceptance. An amend that changes price or quantity upward creates a new priority; nothing else moves you in the queue.

Exact integer arithmetic. Prices are integer ticks, quantities integer lots, money integer micro units. Notionals are staged through 128-bit intermediates and rounded by an explicit rule (ceiling for margin, half-even for fees), never by floating point. Two members computing the same fill from the same inputs get the same answer to the last micro unit, which is what makes the reconciliation endpoints meaningful.

Self-trade prevention

STP applies when two orders of the same member meet and are not exempted by scope. Under the default END_CLIENT scope, two of your orders with different clientUid values are not a self-trade at all and execute normally. Orders carrying the same clientUid never trade with each other; your configured policy applies instead.

PolicyOutcomeWhat you observe
CANCEL_RESTING (default)The resting order is cancelled; the taker continues walking.Unsolicited cancel with STP_CANCEL, then normal fills.
CANCEL_TAKERThe incoming order is cancelled; the book is untouched.Cancel with STP_CANCEL on the taker.
CANCEL_BOTHBoth sides are cancelled.Two cancels with STP_CANCEL.
REJECT_TAKERThe taker is refused.If it has not yet traded, REJECTED with code 2015. If it already partially filled, it cannot be un-accepted, so it is CANCELED with STP_CANCEL instead.

That last row is the one to code for. Under REJECT_TAKER the same logical event reaches you as a reject or as a cancel depending on whether any quantity had already traded, so a state machine that expects only one of the two will desynchronise on a busy book.

Market Segments

Market Segments is the venue's counterparty-acceptance mechanism: you may restrict which members you are willing to trade with, and matching requires mutual acceptance. The default is open to all. Restricted liquidity stays visible in the full public book (the venue never hides depth), but your matchable book, GET /v1/orderbook/matchable, shows only what you can actually hit, and it is that book your pricing logic should read. Ineligible resting orders are skipped during the walk and keep their queue position; they are neither cancelled nor disadvantaged. Price-time priority is therefore honoured strictly within your accepted set, which means you can print at a worse price than the visible top of book when the better-priced liquidity belongs to a member outside your set. Segments apply identically on perp and spot markets. They do not apply to ADL, which is a rulebook disclosure rather than an oversight: a deleveraging cannot be selective about its counterparties and remain fair.

Margin, leverage and fees

Margin is computed and enforced at member level only, cross-margined per settlement currency. Initial margin (IM) is charged on positions and on working orders; maintenance margin (MM) is the level below which the liquidation waterfall opens.

Sandbox tiers match production. Every listed perpetual carries the same three-tier ladder in both environments: initial margin 2 percent up to 1 million USD notional, 5 percent to 5 million, 10 percent above, maintenance margin half of each tier's rate. Read the live values from GET /v1/instruments per environment rather than this page. The production listing as planned today also uses the sandbox's grid and minNotional on every market both environments list. Two deliberate sandbox-to-production differences remain: the sandbox funding rate on the GRID perpetuals is fixed, and the stale-mark timeout is 60 seconds on the sandbox (300 seconds in production) so the staleness ladder can be exercised quickly. Production lists the perpetual and the knock-out markets; its instrument list differs from the sandbox's and is confirmed with the go-live listing. Production ISINs are pending DSB issuance.
POST/v1/margin/preview

Send {"orders": [ ... ]} with the same bodies you would place, and get back indicative accepted, im, mm and available. The array is priced as one basket of 1 to 50 entries: all of them together, on top of what you already hold, with the same one-sided netting per instrument that resting orders receive, so it answers "would ALL of these clear at once" and the result does not depend on array order. It runs the identical margin function the engine runs, on the identical state, so it is the correct way to answer "will this be rejected" without consuming your order bucket. It is a read, not a write, and a READ_ONLY credential can call it.

accepted applies the same admission rules order entry applies, entry by entry: available, the per-order size cap, the minNotional floor, the position cap and the reduce-only budget, with the reduce-only exemptions intact. A reduceOnly entry is exempt from the available gate, from minNotional and from the position cap exactly as it is when you send it, so a reduce-only basket previewed during a margin call answers accepted: true, which is the answer that matters when you are trying to get smaller. It is not exempt from the per-order size cap, and it is held to the reduce-only budget instead of the position cap: a reduceOnly order may only close what you hold, so a basket that would close MORE than your open position on that market (counting the reduce-only quantity already working) answers accepted: false, because sending it would place the first entries and reject the surplus with 2008. A MARKET entry is valued at the current mark, on perpetual and spot markets alike, which is the same price the per-order cap and the minNotional floor use; the collar a market order actually takes forms from the book at the instant of entry, so treat a market entry's answer as an indication at today's mark rather than a quote.

The venue does not enforce per-end-client leverage. You do. The venue margins your member account on the published tier ladder and does not model, check or limit leverage per end client. If you offer clients a flat 10x, enforce it before you submit. The optional order-level leverage field is an assertion, never a control: the venue validates it against your account's effective margin and rejects a false one with 2018, but it never changes the margin applied and never caps anything. It can only hold on an instrument with a single open-ended risk tier whose effective IM rate (tier rate times your imMultiplier) is exactly 1/leverage; on a tiered instrument, effective leverage is size-dependent and no whole-number assertion can be true, so every value is rejected. quoteCcy works the same way and rejects with the same code.

Fees are maker and taker rates per member, visible as makerFeeRate and takerFeeRate on GET /v1/account (null means the instrument default applies). Rates come from your fee tier, agreed at onboarding. They are applied to the fill notional, rounded half-even per fill, charged in the settlement currency at fill time, and visible on the wallet channel and in the ledger.

A negative maker rate is a rebate. makerFeeRate can legitimately be negative, meaning the venue pays you to provide liquidity. Your fee accounting must handle a negative fee as a credit rather than clamping it to zero or treating it as a parse error. Taker rates are never negative.

Funding settles on every perp at fixed UTC anchors, interval per instrument and 8 hours on all current instruments. A positive rate means longs pay shorts. Funding moves cash, so it can move you into a margin call between two of your own orders. Funding settles EVERY elapsed anchor: after a venue outage spanning several anchors you receive one FundingSettled event and one ledger entry per missed anchor, each computed at the rate in force (the published fixedRate on a market whose funding.rateSource is FIXED, else the last sequenced tick rate) and the last sequenced mark, at most 8 anchors per settlement with any remainder following on subsequent timer ticks about 30 seconds apart, and GET /v1/funding/history row counts reflect every settled anchor. Funding never settles on a mark the venue holds as stale (revision 3.70): while a market is in reduce-only for STALE_MARK_PRICE, or its last mark is older than the market's staleness threshold, due anchors wait and are settled at the first settlement after the market leaves reduce-only, each at the then rate in force and mark on the positions held at that settlement, with the anchor as settleTs and the settlement time as settledTs on GET /v1/funding/history; the catch-up after a venue outage waits for the mark feed the same way. Funding catch-up fence (revision 3.70): while a GRID perpetual's next settlement is more than 60 seconds overdue (after an outage or a leadership change, until the catch-up settlement lands) the venue refuses every order that does not carry reduceOnly (a client-level close sent without the flag included, stated since revision 3.80), every non-reduce-only amend and every RFQ acceptance on that market with code 3014 FUNDING_CATCH_UP, and a conditional order whose trigger fires inside the window is canceled with cancelReason FUNDING_CATCH_UP instead of executing; reduce-only orders and amends are admitted throughout. The fence makes the positions charged for a missed anchor exactly the positions that held through the gap. It lifts on the settlement itself, the FUNDING_SETTLED events, normally within one to two seconds of the venue resuming; retry then, or poll GET /v1/funding/current until nextFundingTs lies in the future. The venue settles every overdue anchor before it opens any listener after a restart, so in the ordinary case the window is closed before you can reconnect. Both rules are dormant on the sandbox until the operator decision batch epoch announced by venue operations and live on production from the first day.

Spot markets

Spot instruments ("kind": "SPOT") trade the base asset against the settlement currency with real delivery and full prefunding. No leverage, no short selling, no funding, no positions and no liquidation of spot balances. The order model, the book, market data, STP and Market Segments behave exactly as on perps. The differences are all about funding.

Current spot listings (revision 3.50, sandbox; informative, always read GET /v1/instruments): BTC-USD, ETH-USD, SOL-USD, BNB-USD and XRP-USD, each a central limit order book ("mode": "ORDER_BOOK") on the plain pair symbol, one book per base asset, USD-quoted and USD-settled, sized exactly like the perpetual of the same underlying (tick 0.5 / 0.05 / 0.01 / 0.05 / 0.0001, qtyStep 0.0001 / 0.001 / 0.01 / 0.001 / 1, minNotional 5 USD, maxOrderNotional 10000000 USD, fees 0.0002 maker / 0.0005 taker). The base asset codes BTC, ETH, SOL, BNB and XRP are the asset values of the assets array on GET /v1/account and the ccy of the asset legs on the private wallet channel; asset balances are decimal strings with up to six decimal places. Spot markets are offered under the venue's MiCA notification: spot fills are not MiFIR transactions, so no RTS 24 order record or RTS 22 transaction report is produced for them.

RuleDetailReject
Buys need quote cashAt entry the venue reserves the worst-case quote leg: notional at the limit price (or the collar for market orders, or the post-trigger limit price for conditionals), plus the fee at your worst applicable rate, plus a small rounding slack. Insufficient free cash rejects.3001
Sells need the base assetYour free base-asset balance must cover the full remaining quantity. This check is balance-based, never equity-based: unrealized PnL is not an asset you can deliver.3004
reduceOnly is unsupportedThere are no positions to reduce.2016
Market-conditional buys are unsupportedSTOP_MARKET and TAKE_PROFIT_MARKET on the buy side have no computable worst-case cost at placement, because the collar only forms at activation, so there is nothing to prefund. Stop-limit and take-profit-limit buys, and all conditional sells, are supported.2016
Reduce-only sessionsDuring a volatility or stale-mark reduce-only session, spot sells stay allowed (they only raise cash); spot buys are blocked.3002

Reservations are bookkeeping, not escrow, and this has a consequence you must handle:

SPOT_UNFUNDED at fill time. Spot quote reservations and perp margin draw on the same settlement-currency account. A realized perp loss or a funding payment after your spot buy was accepted can leave that resting order unaffordable. Rather than settling into a negative balance, the engine re-checks funding at execution time with the exact arithmetic settlement would use and cancels the order with cancelReason: "SPOT_UNFUNDED". The same applies to a seller whose asset balance was moved. This is an unsolicited cancel of an order that was valid when you sent it, so treat it as a first-class event, not an error path.

Settlement is per fill and atomic: the buyer pays notional plus fee and receives the asset; the seller delivers the asset and receives notional minus fee. Because spot trades on the perpetual's fractional grid (qtyStep 0.0001 on BTC-USD, and so on; revision 3.50, earlier revisions said whole units, which described the pre-listing fixture, never a rule), price x qty is exactly your cash leg and qty exactly your asset leg: a fill of 0.0003 BTC at 70000 moves exactly 0.0003 BTC and 21 USD. Asset movements appear on the wallet channel with the asset code in ccy; GET /v1/positions never contains spot rows, and holdings live in assets on the account. Spot asset holdings are not collateral for perp margin.

RFQ markets

Every instrument on GET /v1/instruments carries a mode: ORDER_BOOK or RFQ. Everything above this heading describes order-book markets. An RFQ market has no order book at all: no depth, no resting orders, no conditionals, no order entry. Sending an order to an RFQ market is rejected with 2022, and sending an RFQ operation to an order-book market is rejected with 2023, so a client that confuses the two surfaces fails loudly on its first message. Read the mode at startup with the rest of the instrument record and route accordingly.

Trading on an RFQ market is negotiated in three moves: you open a request, eligible members quote it, you accept exactly one quote. What the accepted quote produces depends on the instrument kind.

KindAn accepted quote producesEconomics
PERPAn off-book perp trade at the quoted price.Margined and netted exactly like a book fill; the execution carries flag RFQ. One risk consequence of having no book: a member liquidated while holding a position on an RFQ perp market has that position closed AT THE MARK against opposite-side holders in deleveraging order, profitable positions first, in one step; where the profitable side cannot absorb the whole position, the remaining opposite-side positions, including positions not in profit, are closed at the same mark price. Such a close arrives as an ADL-flagged trade at the mark price, and unlike classic auto-deleveraging it does not require the defaulter to be bankrupt first.
SPOTPrefunded delivery at the quoted price.Same funding rules as book spot: the buyer's cash and the seller's asset are checked at execution and settled atomically.
BARRIERA bilateral knock-out contract.Covered in full below. Barrier markets are always RFQ.
SWAPNot a quote at all: a TAKE of a writer's standing OFFER, opening a yield contract.Covered in full below (revision 3.51). Swap markets are always RFQ, and the verbs run the other way round: the writer posts, any other member takes, nobody quotes.

Request, quote, accept

POST/v1/rfq
{
  "symbol": "BTC-USD-KO",
  "side": "BUY",
  "qty": "2",
  "expiresInMs": 60000,
  "barrier": { "level": "65000" },
  "clOrdId": "r8c2e5a71d4b0f36",
  "clientUid": "CLIENT-A"
}

expiresInMs is the quoting window, default 60000; the engine accepts 1 second to 24 hours, and a window outside those bounds rejects with 2013. qty is a decimal number of units on the qtyStep grid (the perpetual's step on the barrier markets since revision 3.71) and obeys the grid and the order-size cap exactly as an order does (2002 off the grid; 2013 over the cap: maxOrderNotional valued at the current mark where published, else the base-unit maxOrderQty), and the minimum notional applies (100 USD on every barrier market since revision 3.71, 5 USD elsewhere): a request below minNotional valued at the current mark rejects with 2028, as does a quote below it at its quoted entry price, and a close request is valued at the contract's whole quantity, so a contract worth less than the floor at the mark ends at its barrier, its take profit or its expiry and not by an early close. clOrdId, clientUid and the reserved KX- prefix (2020) behave exactly as on order entry, and the Trader ID gate is identical too: a missing or unregistered reg.traderId rejects with 2021 on create, on quote and on accept. The barrier block is required on barrier markets and must be absent on perp and spot RFQ markets (2027 either way); unknown fields reject with 2017. You may hold at most 64 open requests at once (2012).

StepEndpointRules
DiscoverGET /v1/rfq/openThe open board: every live request you are eligible to quote, requester anonymous. Your own requests are never on your board.
QuotePOST /v1/rfq/{rfqId}/quotesprice plus a validity expiresInMs, default 30000, same 1 second to 24 hour bounds. One live quote per maker per request: a re-quote replaces yours, under a NEW clOrdId since Member API revision 3.85 (a request or a quote whose clOrdId you already used answers 2009 and opens or replaces nothing, from the venue's replay-contract line for that release). A request holds at most 64 live quotes (2012). Quoting commits you to the request's FULL size, so it counts against your order-size cap exactly like a book order of that size (2013: maxOrderNotional valued at your quoted entry price where published, else the base-unit maxOrderQty). Quotes are band-checked against the mark (2003) even though the price is negotiated: the band is the fair-and-orderly backstop.
WatchGET /v1/rfq/mine or WS rfqThe requester sees each quote's quoteId, price and validity, never the maker's identity. Makers track their own quotes on GET /v1/rfq/quotes/mine.
AcceptPOST /v1/rfq/{rfqId}/accept{"quoteId": ...}. Exactly one quote wins and the request closes. The response carries the tradeId, and on a barrier market the contractId. The band is re-checked against the CURRENT mark at accept: a quote the market has drifted away from is stale and rejects with 2003 rather than printing off-market. On a barrier OPENING accept the barrier accept guard (revision 3.55; in force on every environment) additionally requires the entry within the market's barrierGuard.entryBandBps (50 bps unless the market sets its own) of a FRESH mark (2039), a takeProfit the mark has not reached (2040), a barrier the mark has not reached or crossed (2043) and both levels at least the market's barrierGuard.minTakeProfitBps / minBarrierBps of the entry (10 bps unless the market sets its own) away from it (2041 / 2042); a refused accept leaves the request and the quote open. Both members must still be fit to open new risk at that moment: a reduce-only requester sees 3002, a reduce-only maker's quote resolves 2025.
CancelPOST /v1/rfq/{rfqId}/cancel and POST /v1/rfq/{rfqId}/quotes/{quoteId}/cancelWithdraw your request or your quote. Never rate-limited, exactly like order cancels.
An RFQ print is not book liquidity. The trade publishes on the public trades feed flagged RFQ (BARRIER_CLOSE for the closing trade of an accepted barrier close request, revision 3.44) and lands in both parties' executions, and the requester pays the taker fee while the maker pays the maker fee, at your ordinary rates on the trade notional. But it does not move the last-trade print, it never fires a conditional order and it does not feed the circuit breaker: a bilaterally negotiated price is not public book liquidity, and a feed consumer that treats an RFQ print as one will mislead itself about where the market is.

RFQ trading is available over REST, with lifecycle pushes over WebSocket. There is no FIX representation of any RFQ message.

Barrier contracts

A barrier contract ("kind": "BARRIER") is a cash-settled knock-out traded only by RFQ. The requester is always the holder: BUY opens a long with the knock-out barrier below the entry, SELL opens a short with the barrier above. The maker writes the contract, and its quote is the entry price. The terms ride the request: barrier.level is required and must sit on the knock-out side of the current mark; barrier.expiryTs (Unix ms, must be in the future) is optional on a market that publishes no maxContractLifeHours, and without it the contract is open-ended there; a market that publishes one (revision 3.70, GET /v1/instruments) requires it at most that many hours after the request (2027 otherwise); barrier.takeProfit (revision 3.43) is optional too, a second exit level on the PROFIT side of the entry (above the mark and the entry for BUY, below both for SELL, so the two levels always bracket the entry) at which the contract also terminates AT the level, fee-free like the knock-out. Both levels are re-validated against the quoted entry at quote time and again at accept, so a negotiation can never place the barrier or the take profit on the wrong side of the entry price. barrier.strictTakeProfit (revision 3.45) is an optional flag on top: a STRICT take-profit contract pays only if the take profit is touched before the contract expiry and needs a takeProfit plus an expiryTs at most 24 hours ahead (below). Every terms violation is 2027. The barrier accept guard (revision 3.55; in force on every environment) additionally fences the OPENING accept against the CURRENT mark: entry within the market's barrierGuard.entryBandBps (50 bps unless the market sets its own; on the sandbox 20 bps on the FX knock-out markets (EUR, GBP and JPY, and since revision 3.75 USDJPY) and 30 bps on the gold and index knock-out markets (XAU, SP500 and NDX100, and since revision 3.75 US500 and US100) from the date venue operations announce) of a fresh mark (2039), no already-reached take profit (2040) or barrier (2043), and both levels at least the market's barrierGuard.minTakeProfitBps / minBarrierBps of the entry (10 bps unless the market sets its own) away from it (2041 / 2042); a refused accept leaves the request and the quote open. Writers: refresh or withdraw your quotes when the mark moves; an unexpired quote can otherwise be accepted against you right up to those fences.

Barrier contracts are bilateral. They never appear in GET /v1/positions, never contribute to open interest and never touch your perp netting. They live on GET /v1/barriers, one row per contract, with your role (HOLDER or WRITER), direction, qty, entry, barrier, the optional take profit, strictTakeProfit, the holder's premium and its premiumBps (revision 3.45), the live mark, barrierDistance (distance to knock-out as a fraction of mark), your role-signed unrealized PnL and your margin; ?status=CLOSED lists your recently settled contracts with the settlement price, your realized PnL and the terminationReason (KNOCK_OUT, TAKE_PROFIT, EXPIRY, TEAR_UP, FINAL_SETTLEMENT, EARLY_CLOSE). The barrier market is its own instrument with its own symbol and its own mark price feed (BTC-USD-KO on the sandbox); knock-out and expiry key off that mark and nothing else. There is no funding on barrier markets.

Early close by RFQ (revision 3.44)

The holder of an open contract can ask its writer to close it before the barrier, the take profit or the expiry gets there. The request is an ordinary POST /v1/rfq on the contract's market that names the contract instead of describing a trade:

{
  "symbol": "BTC-USD-KO",
  "closeContractId": 51,
  "expiresInMs": 120000,
  "clOrdId": "r8c2e5a71d4b0f37"
}

closeContractId is the id of an OPEN contract you HOLD on symbol (from GET /v1/barriers, role HOLDER). side, qty and barrier must be OMITTED (any of them present rejects 2013): the venue derives the CLOSING side (a long holder SELLs, a short holder BUYs), the full contract quantity and the contract's terms, and every RFQ view echoes them together with closeContractId. expiresInMs, clOrdId and reg behave as on any request; clientUid may be omitted (it defaults to the contract's holder-side client) or must equal it (2010). Only the holder may request, at most ONE close request per contract at a time, and an id that is not an open contract you hold on this market rejects 2035 (also when a close request is already open for it, and at accept when the contract terminated between the steps).

Only the writer sees it. A close request is on the board of the contract's WRITER only (GET /v1/rfq/open, and the WS rfq created frame is delivered to the writer with role WRITER); no other member ever sees it, and any other member quoting it is answered 2024. The writer's quote is the price the contract CLOSES at: tick-aligned (2002), inside the price band (2003) as always, and STRICTLY INSIDE the contract's terms relative to the holder's direction, barrier < price < takeProfit for a long holder (when a take profit exists) and mirrored for a short holder, otherwise 2027: a price at or beyond the barrier would exceed the guaranteed maximum loss, at or beyond the take profit the guaranteed maximum gain. Re-quotes replace as always.

Accept closes at the quoted price. The holder's POST /v1/rfq/{rfqId}/accept prints the closing trade, flagged BARRIER_CLOSE (a value in the flags vocabulary above RFQ, so trade history, drop copy and transaction reporting tell a contract's close from its entry), which pays ordinary maker/taker fees exactly like the entry trade (holder taker, writer maker, on qty x price x contract value); then settles the contract BARRIERSETTLE zero-sum, holder PnL = direction x (price - entry) x qty x contract value and the writer the negation, with terminationReason EARLY_CLOSE; and the accept response carries contractId (the closed contract), closeContractId, settlePrice (the quoted price) and your realizedPnl beside the trade fields. The accept re-checks that the contract is still open and held (2035), that the quote still lies inside the terms (2027), the band against the current mark (2003) and member statuses as always. There is NO margin admission check for a close, because closing releases margin; only the exact-money fence stays (2027).

Coupling. While a close request is open the contract refuses a second one (2035). If the contract terminates first, by knock-out, take profit, expiry, tear-up or final settlement, the venue CANCELS the open close request in the same command (an rfq canceled frame, an ordinary cancel), so no quote can land on a contract that no longer exists; when the request ends (accept, cancel, expiry) the contract is free for a new one. Cancelling a close request (POST /v1/rfq/{rfqId}/cancel) is free like every cancel.

The premium, the knock-out rebate and the strict take profit (revision 3.45)

The holder's maximum loss on a contract is its premium: a share of the entry-to-barrier distance times quantity, |entry - barrier| x qty x contract value x premiumBps / 10000 (floored to 6 places). premiumBps is FROZEN on the contract at the open and published on every barrier surface: 10000 - knockOutRebateBps on a normal contract, where knockOutRebateBps is the market's knock-out rebate from GET /v1/instruments (1000 bps = 10 percent on every barrier market listed today, so the premium is 90 percent of the distance); the market's strictTakeProfitPremiumBps on a strict take-profit contract (5000 bps = 50 percent today); and 10000, the full distance, on every contract opened before the rebate existed. The premium is what the holder margins at entry, what it loses at a knock-out (the writer receives it, and the rebate share of the distance is what the holder recovers from the writer at that moment) and the floor of every other settlement.

Strict take profit. barrier.strictTakeProfit: true asks for a contract that pays ONLY if the take profit is touched before the contract expiry: at the expiry without a touch the holder loses the whole (strict) premium whatever the mark, however close it is (terminationReason EXPIRY, holder realizedPnl = minus the premium), and "before" is strict: a price tick that arrives at or after expiryTs settles the expiry even if that tick is at or beyond the take profit (a normal contract's take profit is guaranteed on such a tick, a strict contract's is not). It requires a takeProfit, an expiryTs at most 24 hours after the request and a market whose strictTakeProfitPremiumBps is nonzero, else 2027; the share is re-checked at accept and frozen onto the contract. A knock-out, a take-profit touch and an early close settle exactly as on a normal contract; only the expiry differs. Absent or false = a normal contract.

 Holder (requester)Writer (maker)
MarginThe premium, reserved at entry (IM equals MM); the requirement then tracks the most you can still lose, the remaining mark-to-barrier distance less the knock-out rebate (the premium plus your unrealized PnL, floored at 0). A take profit does not change it.Margined like a perp on the market's risk tiers at current notional, IM scaled by your imMultiplier; when the contract carries a take profit, the SMALLER of that figure and the remaining mark-to-take-profit distance times qty (a bounded contract never over-margins the writer). The rebate you give back at a knock-out adds no requirement: you still receive the premium there, and your worst case stays the take-profit side.
Maximum lossExactly the premium. The knock-out is the risk limit; on a strict contract the expiry without a touch costs the same premium.The holder's gain is your loss, margined continuously on the tiers as the mark moves; with a take profit set it is bounded by the take-profit distance times qty (the potential profit).
EquityUnrealized PnL marks to market continuously into your equity, floored at minus the premium.The exact negation of the holder's, likewise marked continuously.

Tear-up is two-sided: a member entering liquidation, holder or writer, has every barrier contract it is party to closed at the barrier-clamped mark inside the episode, its open requests cancelled and its outstanding quotes withdrawn. The contract itself, however, can never cause its holder's liquidation: the holder's requirement is the REMAINING distance from the mark to the barrier less the rebate (IM equals MM), so the unrealized loss and the released requirement cancel tick for tick and the holder's equity-minus-MM contribution stays constant, at minus the premium, from entry to knock-out. An account funded with exactly the premium rides to the barrier and ends at zero, never in an episode. The flip side: unrealized profit on the contract stays reserved until the contract closes, and losses on the member's OTHER positions remain able to force the whole account into liquidation.

The barrier is a guaranteed stop. When the mark touches or crosses the barrier, the contract terminates AT the barrier price, whatever the mark actually printed. If the mark gaps straight through the level in one tick, you still settle at the barrier. This is the property that distinguishes a barrier contract from a perp position with a stop order: a stop can slip, the barrier cannot. The optional take profit is guaranteed the same way on the other side: when the mark reaches it the contract terminates AT the take-profit price, gap or no gap, and because the two levels sit on opposite sides of the entry one tick can never cross both.
EventSettles atFees
Entry (accept)The quoted entry price.Ordinary maker/taker fees on the entry notional: holder pays taker, writer pays maker.
Knock-outThe barrier price, on the mark tick that touches or crosses it. Holder loss = the premium (the writer receives it; the rebate share of the distance is what the holder recovers, revision 3.45).Fee-free.
Take profit (when set)The take-profit price, on the mark tick that reaches or crosses it (long: at or above, short: at or below). Holder profit |takeProfit - entry| x qty, in full, strict or not.Fee-free.
ExpiryThe mark, on the first price tick at or past expiryTs: on a normal contract the price PnL floored at minus the premium and capped at the potential profit; on a STRICT take-profit contract (revision 3.45) minus the premium whatever the mark, since a touch would have settled it already.Fee-free.
Early close (revision 3.44)The writer's accepted quote, strictly inside the terms, on the holder's accept of its close request. Holder PnL = direction x (price - entry) x qty, clamped to [minus the premium, plus the potential profit].Ordinary maker/taker fees on the closing notional, exactly like the entry: holder pays taker, writer pays maker; the trade is flagged BARRIER_CLOSE.
Liquidation tear-upThe mark, clamped to the contract's terms (never beyond the barrier or the take profit); holder PnL floored at minus the premium.Fee-free.
Final settlement (delisting)The operator-determined close-out price, clamped to the terms; holder PnL floored at minus the premium.Fee-free.

A close books its PnL as a zero-sum pair of ledger entries of kind BARRIERSETTLE, the holder's PnL against the writer's exact negation, visible on the wallet channel and in the ledger like any other cash movement (an early close books its fee legs separately, as ordinary FEE entries against the closing trade). A close at exactly the entry price has nothing to book.

How many contracts you may hold at once. Alongside the size caps, an accept is refused if it would take you past 256 open barrier contracts (holder or writer, all barrier markets together), or take the market past 4096 open contracts. Your own limit answers 2011; the quoting member's answers 3007, the same codes the size caps use. These bound how much work each open contract adds to every margin calculation and every price tick, they are not risk limits, and they release as contracts knock out, take profit, expire or settle. No member is near either.

Worked example. You accept a quote of "70000" on a BUY of "2" BTC-USD-KO with barrier "65000" on a market with a 10 percent knock-out rebate (premiumBps 9000). Premium, reserved at entry: (70000 - 65000) x 2 x 0.9 = "9000" USD, IM and MM alike (the full distance would be 10000; the rebate is 1000). The requirement then tracks the REMAINING distance to the barrier less the rebate. Mark rises to "72000": unrealized PnL +4000, requirement now (72000 - 65000) x 2 - 1000 = "13000", so the gain stays reserved rather than freeing margin. Mark falls to "66000": unrealized PnL -8000 and the requirement is down to "1000"; the loss and the released requirement cancel exactly, so the contract never moves you toward maintenance on its own. Mark touches "65000": the contract terminates at "65000" and your realized loss is exactly "9000", the premium you posted, no more: the writer receives 9000, and the 1000 rebate is the part of the distance you never lose. If instead the mark gaps from "66200" straight to "64100" in a single tick, you still settle at "65000" and still lose exactly "9000": the overshoot never reaches your account. Entry fees were charged once, on the 140000 entry notional at your taker rate; the knock-out itself is fee-free. The same contract as a STRICT take profit with takeProfit "75000" and an expiry two hours out (strictTakeProfitPremiumBps 5000): premium (70000 - 65000) x 2 x 0.5 = "5000"; a touch of 75000 pays (75000 - 70000) x 2 = "10000", a knock-out costs 5000, and an expiry with the mark at 74900 costs the whole 5000.

Yield contracts

A SWAP market ("kind": "SWAP", always RFQ; six on the sandbox: USD-TBILL-SWAP, EUR-TBILL-SWAP, BTC-STAKE-SWAP, ETH-STAKE-SWAP, SOL-STAKE-SWAP, USD1-STAKE-SWAP) trades a bilateral yield contract in ONE asset, the market's baseAsset. A writer posts a standing offer with POST /v1/rfq: qty (the size on offer), rateBps (the annualised rate it pays, whole basis points), tenorDays, an optional minQty (smallest single take, floor: the market's minNotional) and expiresInMs (validity 60 s to 30 days, default 24 h); no side, no barrier. Any other member takes a size with POST /v1/rfq/{rfqId}/accept and qty, no quoteId; the board of offers is GET /v1/rfq/open?symbol=, writers anonymous, best rate first, your own offers excluded. Partial takes are normal (remainingQty on every view; a take below the minimum is admitted only when it clears the whole remainder); the writer withdraws the rest with the ordinary cancel; the offer lapses at its validity end.

Each take is a contract. The taker's qty moves to the writer at once as principal (a SWAPPRINCIPAL wallet entry in the asset), both pay the market's fee on the notional in the asset (writer maker 1 bps, taker taker 2 bps on every listing, the instrument rates for every member since revision 3.70: fee tiers and programmes do not apply on swap markets; nothing at maturity), a trade flagged SWAP prints with price = the rate in basis points, and reward = floor(notional x rateBps x tenorDays / 3,650,000) in the asset (ACT/365, floor to the 6th decimal) is frozen. At maturity, exactly tenorDays x 24 h after the take, the venue's timer pays principal plus reward from the writer to the taker (a SWAPSETTLE entry): in full, the contract closes MATURED; short, the part the writer can pay moves, the rest stays as the taker's CLAIM (contract DEFAULTED), the writer's offers are withdrawn, it may post no new offer while any claim of its is open (3008), and every later tick retries the claim from whatever it can then pay until the contract closes CURED. A halted swap market takes no offers or takes but still matures; a delisting withdraws every standing offer on the market and then settles principal plus the pro rata reward (FINAL_SETTLEMENT). A writer in default management on the venue (in liquidation or default) pays no swap settlement while it lasts, exactly like a withdrawal: such a maturity leaves the whole due as a claim, cured in full on the first tick after the freeze lifts. Contracts ride through a party's liquidation and cannot be closed early. Your contracts, both roles, are GET /v1/swaps; nothing about a swap ever appears in GET /v1/positions, open interest or margin.

The writer's obligation is unsecured. The venue never verifies what the writer does with the asset, holds nothing against the return of principal and reward, and settles a short writer partially, leaving a claim that is paid only from the writer's later balance. Members offering swap markets to their own clients must disclose this. The full economics, the caps (maxOrderQty per offer and per take, maxPositionQty per member and market, 256 live contracts per member, 4096 per market) and the contract specification sheet are in the member reference section 6h.

Streaming and recovery

Three private channels cover the whole lifecycle, all with guaranteed delivery.

ChannelEvent typesWho receives
rfqcreated, canceled, expired, quoted, myQuote, quoteCanceled, acceptedYour requests: created, canceled, expired, plus quoted for each anonymous quote. Your quotes as maker: myQuote, quoteCanceled. accepted goes to both parties with role REQUESTER or MAKER. Every frame carries closeContractId when the request is a close request (revision 3.44); a close request's created is ALSO delivered to the contract's writer, with role WRITER. On barrier markets created frames also carry strictTakeProfit, premiumBps and the indicative premium at the current mark (revision 3.45).
barriersopened, knockOut, takeProfit, expiry, earlyClose, liquidation, finalSettlementBoth parties to the contract, with the terms, strictTakeProfit, premium and premiumBps (revision 3.45) on every frame, and the settle price, role-signed PnL and terminationReason on every close.
swapsopened, matured, default, cured, finalSettlementBoth parties of a yield contract (revision 3.51), each frame with your role, the terms, status, paid / outstanding on settlements and a role-signed amount. On a swap market the rfq channel carries the OFFER lifecycle instead (created, canceled, expired to the writer; accepted to both parties of a take with role, qty, remainingQty, contractId).

The open board is deliberately not pushed: poll GET /v1/rfq/open. Pushing every new request to every member would leak across Market Segments. The one push beyond the requester is the close request's created frame to the contract's writer: it has exactly one eligible quoter, so nothing leaks.

Guaranteed, but state-only on recovery. Unlike order, execution and wallet, the rfq and barriers families are not cursor-backfillable and never appear in a gap frame's backfill query. After a gap or a reconnect, re-read GET /v1/rfq/mine, GET /v1/rfq/open and GET /v1/barriers, then resume from the live stream. Those reads are the complete current state, which is all an RFQ workflow needs: a request or quote whose birth you missed is either on the board now or already gone. The swaps family (revision 3.51) is the exception: it IS cursor-backfillable like wallet, and GET /v1/swaps is its state read.

The RFQ surface adds twelve codes to the registry. As everywhere, the numeric code is the contract and the message is advisory.

CodeHTTPMessage
2022400RFQ market: no order book, trade via POST /v1/rfq
2023400not an RFQ market: use the order book
2024404RFQ not found, closed or expired
2025404quote not found, withdrawn or expired
2026400cannot quote or accept against your own member
2027400barrier level or expiry invalid for this market and side (also a take profit on the wrong side, a close-request quote outside the terms, and a strict take-profit request without a take profit, without an expiry, with an expiry beyond 24 h, or on a market that does not offer it)
2035400closeContractId does not name an OPEN barrier contract you hold on this market, or a close request for it is already open
2036400swap offer terms outside the market: rate, tenor, size, minimum take, validity or the exact-money ceiling (revision 3.51)
2037400swap markets have offers and takes, never quotes: a quote on a swap offer, or a swap accept with a quoteId
2038400swap take size not admissible: zero, above the remainder, above your per-order cap, or below the minimum take without being the remainder
3007400quoting member no longer passes margin or limits (on a swap take: the writer is no longer fit and the offer is withdrawn, or the writer is at its caps and the offer stays)
3008400swap writer blocked: a contract you wrote carries an outstanding claim

Venue-initiated flow

The venue acts on your account without a request from you. There are exactly four mechanisms and none of them is optional to handle.

Margin call

When equity falls below total initial margin, your riskStatus becomes MARGINCALL and a MARGIN_CALL message with state: "ACTIVE" is published on the venueEvents channel, carrying equity, IM, MM, available and the currency. Recovery publishes CLEARED. Nothing is cancelled and nothing is closed at this stage: it is a notice. Add margin or reduce.

Liquidation

When equity falls below maintenance margin while you hold exposure, an unwind episode opens and the waterfall runs in a fixed order. Automatic DETECTION pauses while any market the member holds a position, an open order or barrier exposure on is stale (the staleness reduce-only overlay) or has no mark price yet: the breach re-detects and the episode starts on the first margin sweep after the market recovers. A liquidation ordered by venue operations is not gated by this pause.

  1. Your entire order book is cancelled, venue-wide. Every working and pending order across every instrument, perps and spot alike, with cancelReason: "LIQUIDATION_CANCEL". This happens first because cancelling releases order margin and may cure the breach on its own. It is not scoped to the instrument that caused the problem, and a member whose systems have no unsolicited-cancel concept will lose its book without understanding why.
  2. Paced closing orders. The venue then works IOC limit orders against the book on a fixed cadence, picking the instrument giving the largest maintenance-margin relief per lot, sizing each slice as a configured fraction of the net position, and pricing at the mark offset by a configured aggression. The episode pauses on an instrument whose mark has gone stale rather than closing you into an unreliable price.
  3. Allocation across your end clients. Each slice is split pro rata across the sub-positions holding the same direction, floor pro rata by size with the remainder going to the largest, so every liquidation fill names the clientUid it reduced. Each synthetic order carries the reference KX-LQ-{orderId}.
  4. The episode closes as soon as a re-check finds you above maintenance margin or flat.

While the episode is open your own order flow is frozen: new orders and amends reject with 3002 on risk status alone, whatever your member status shows; cancels stay accepted, and withdrawals are refused. The same freeze persists while riskStatus is DEFAULTED after a shortfall, until venue operations clear the default.

ADL

If the book cannot absorb the close and equity has reached zero in a settlement currency where you still hold exposure, the venue tears up matching exposure against counterparty members at the bankruptcy price. Counterparties are selected by a member-level ranking, published to you as a quintile on GET /v1/adl/indicator (5 being first in line): each position scores its unrealized profit as a fraction of its entry notional multiplied by the member's account leverage on that market (divided by it for a losing position), highest score first, ties to the lower member id, refreshed about every 5 seconds; the ranking basis is stated in full on the REST page beside GET /v1/adl/indicator. Candidates are drawn one at a time in ranking order; a selected member's position is closed up to the quantity still needed before the next candidate is touched. Auto-deleveraging reaches you only if you hold the opposite side of the defaulter's market; profitable positions are closed first in deleveraging order, and only where they cannot absorb the whole position does the venue close the remaining opposite-side positions, including positions not in profit, at the same bankruptcy price. Both legs of an ADL trade carry KX-ADL-{tradeId}, and the flag on the execution is ADL. An auto-deleveraging close is credited to the counterparty final and immediate at the close-out price; nothing is withheld against the defaulting member's negative balance, which the venue claims separately, and any later recovery reaches the deleveraged members as a RECOVERYDISTRIBUTION ledger entry (revision 3.30). In extreme conditions a venue-generated close (ADL, the one-step liquidation close on an RFQ-mode market, final settlement of a delisted instrument) executes at the nearest representable price rather than the raw bankruptcy or operator price: the venue caps the close price so the settlement amount stays exactly representable, both legs settle at the same capped price, and final settlement applies one uniform effective price to every sub-position on the instrument. No position of tradable size approaches the cap. Both legs of an ADL execution are fee-free, in the classic case and in the one-step close of a liquidated member's position on an RFQ-mode market: no maker, taker or other fee is charged, and the only ledger entry it books on either side is the realized profit or loss (ADLSETTLEMENT).

ADL mutualises across your end clients. Within an affected member, the torn-up quantity is allocated pro rata across all of that member's end clients holding the same-direction position in that instrument. An end client can therefore be deleveraged with no fault of its own, at a price it did not choose, because of the position of a different member entirely. This is the one mechanism where the venue's member-level risk model produces an effect you cannot attribute to the behaviour of the affected client. Represent it to your clients in advance, in writing. Counterparty eligibility is deliberately not applied to ADL.

Halts and suspensions

Circuit breakers, stale marks, administrative halts and delisting stop trading with a typed reason on venueEvents. Order entry then rejects with 3003 (halted, retry after resume), 3006 (delisted, permanent for that listing) or 3005 (no mark yet). A suspended member's working orders are cancelled and new flow rejects with 3002; the same code covers reduce-only and post-only sessions where your order does not meet the session's requirement, and the liquidation or default freeze described above.

Your stops do not fire into a halted market. Conditional orders are not triggered while the market is halted, including a halt raised by the very run of trades that would have triggered them: when a cascade of stops trips the circuit breaker, the stops still pending at that instant stay PENDING_TRIGGER rather than activating into the halted market, and they are evaluated again on the first qualifying price after trading resumes. That price can be materially different from the one that would have triggered them, which is the whole point of the breaker, so size and place stops on the assumption that a violent move can defer them rather than fill them.

The breaker is armed wherever a market can print. Not only while a market is fully trading: a market in REDUCE_ONLY or POST_ONLY still prints, because two members closing opposite positions cross and because a conditional order placed before the session changed can still fill, and the same band applies there. That is deliberate: a restricted session is where a violent print is most likely and least welcome.

Venue-initiated closes stop at the halt as well. A liquidation being worked through the book stops when the market halts, including when it is the liquidation's own trade that trips the breaker, and the remainder is worked on the first step after trading resumes. The part not yet closed is still the member's position, still margined and still inside the open liquidation; the venue does not keep trading it into a market it has just published as halted. If you are on the other side of that flow, expect fewer LIQUIDATION executions in the instant a market halts and the balance of them after it resumes.

One exception, and only one. A breaker halt raised out of a REDUCE_ONLY or POST_ONLY session carries no resume time and ends only when venue operations end it, so waiting is not bounded by anything. If the member being liquidated has no other market left to work and its equity has already reached zero, the venue closes that position by auto deleveraging at the bankruptcy price on the suspended market rather than carrying an uncollateralised position until a person lifts the halt. It is the same last-resort step the waterfall always ends in, applied one market earlier, and it reaches you as an ordinary ADL on venueEvents and in your executions, on a market whose tradingState is HALTED. Nothing else trades there: the book stays closed and member order entry still rejects with 3003. Every other suspension keeps blocking venue-initiated closes outright, including an operations halt and a breaker halt that carries a resume time, because both of those end at a moment the venue already knows.

Of the four stop reasons, only an automatic circuit breaker with a published resume time ends by itself: it is the only one that carries an expectedResumeTs and resumes with reason CIRCUIT_BREAKER_EXPIRY. Every other halt stays in force until venue operations lift it, which covers three cases: a halt raised by venue operations; an operations resume of a breaker halt, which is final rather than a pause in the published cool-down; and a breaker halt raised while the market was in REDUCE_ONLY or POST_ONLY, which carries no expectedResumeTs, because ending it automatically would put the market back into full trading rather than back into the restricted session it interrupted. Treat expectedResumeTs as the venue's current intention, and RESUME_TRADING as the fact.

A STOP_TRADING can repeat for a market you already hold as stopped. It repeats when the reason changes under it, which happens when venue operations take over a halt the breaker had raised: the message carries the same tradingState with reason: "ADMINISTRATIVE" and expectedResumeTs: null, and it supersedes the earlier message for that market. That is published whether or not a resume time had ever been advertised for the halt being taken over. Replace your stored reason and resume time on every STOP_TRADING rather than ignoring the ones that do not change state; the venue never leaves standing a resume time it will not keep.

reason and expectedResumeTs answer different questions. The reason says who stopped the market, the resume time says whether it ends by itself, and a breaker halt with no resume time keeps reporting CIRCUIT_BREAKER for as long as it is in force, on venueEvents and on GET /v1/status, across venue restarts included. ADMINISTRATIVE means venue operations, always. Do not infer the reason from the presence of a resume time, and do not treat a missing one as an operations halt.

Handling unsolicited flow

Key on refSource, never on the shape of the reference string. Every execution carries refSource: "MEMBER" means clOrdId is your own reference echoed back, "VENUE" means the venue closed the position and no member order ever existed. The current venue references are KX-LQ-{orderId} and KX-ADL-{tradeId}, but the reference format is venue-owned and may gain new forms; refSource will not change. On FIX the same distinction rides on tag 9011.

Two further facts about unsolicited flow. First, venue-generated orders never produce an accept event: a liquidation slice becomes visible only as a fill or a cancel, so a client that requires an accept before it will process a fill will stall. Second, clientUid rides every venue-initiated close and every rejection, so the tuple (clientUid, symbol) resolves any venue action to exactly one of your sub-positions. You are never shown another member's end-client identifiers, on any surface, including ADL allocation reporting.

Before you go live, prove all of this on sandbox: exercise every order type including an unfillable MARKET plus FOK and a rejected POST_ONLY, observe a 2017 unknown-field reject, drive your order state machine through the full cancelReason set including the venue-initiated ones, and reconcile per-client sub-positions against GET /v1/reconciliation/end-client-positions.