Skip to main content

BSL Cancel-Replace Pattern

Cancel-replace lets a liquidity provider or HFT client amend price, quantity, or order flags without manually issuing separate cancel and place calls.

Why it matters

Separate cancel and place operations can expose a strategy to stale quote risk or temporary loss of queue position. Cancel-replace gives the client one operation with one acknowledgement path.

Preferred path

For new integrations, use a signed QuoteReplace or SpotQuoteReplace action inside an order-entry batch:

{
"version": 1,
"actions": [
{
"payload": {
"account": "0x1111111111111111111111111111111111111111",
"nonce": 42,
"ts": 1781190000000,
"action": {
"SpotQuoteReplace": {
"market": 1,
"legs": [
{
"cancel_order_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"side": "Bid",
"price": 999900,
"qty": 100000,
"time_in_force": "post_only"
}
]
}
}
},
"signature": {
"scheme": "EcdsaSecp256k1",
"bytes": [1, 2, 3]
}
}
],
"idempotencyKey": "replace-bid-1"
}

In current private beta, submit it through POST /api/order-entry/binary or the direct compatibility route POST /api/v1/mm/orders/batch.bin with X-BSL-Result-Mode: ack and X-Senticore-Response-Mode: detailed. The canonical POST /api/v1/bsl/orders/compact route uses the same signed compact payload and requires institutional_agent HMAC auth or a provisioned lane key.

For QuoteReplace, a leg with qty: 0 is cancel-only. A leg with nonzero qty places a deterministic child order id derived from the signed parent payload and leg index.

QuoteReplace guarantees

ContractGuarantee
Parent actionOne signed parent action controls all legs and consumes one action nonce.
ScopeExplicit legs only. It does not implicitly replace an entire market, book, side, or all quote-managed orders.
Leg orderFor a leg with cancel_order_id, cancel is evaluated before that leg's replacement placement.
Child identityNonzero-quantity replacement legs derive deterministic child order ids from the signed parent payload and leg index.
AdmissionX-BSL-Result-Mode: ack confirms the configured admission boundary only.
Terminal truthFinal open, filled, canceled, or rejected state comes from receipts, private stream, FIX/BSL drop-copy, or account order reads.

Do not treat HTTP 200 as proof that every replacement order is resting. A risk reject, market halt, post-only cross, stale cancel target, or terminal engine reject can still appear after admission.

If local order-id tracking is incomplete, do not send a wide QuoteReplace range and assume older quotes are removed. First reconcile open orders from private state or run the account-safe cancel-all flow scoped by market/book/side, then seed a new quote family and persist every returned derivedOrderIds[]. The BSL response includes quoteFamilyId on echoed quote-replace legs and aggregated quoteFamilyScopes[] in bsl.reconciliation.quoteReplaceSummary. Those IDs are deterministic for account + market + book + side and are meant for reconciliation and scoped cancel-all recovery; they are not persisted engine-side order tags.

Scoped cancel-all recovery

When a quote engine loses its local order-id map, use the BSL recovery endpoint before publishing a fresh quote family:

POST /api/v1/bsl/orders/cancel-all
Content-Type: application/json
SC-Auth-Version: 2
SC-Key: <institutional_agent key>
SC-Nonce: <monotonic auth nonce>
SC-Signature: <hmac signature>
{
"account": "0x2222222222222222222222222222222222222222",
"market": 7,
"book": "YES",
"side": "Bid"
}

account is the 20-byte engine account. With account-bound institutional_agent auth it may be omitted; otherwise send it explicitly. market, book, and side are optional filters. Omitting all three is a whole-account panic cancel and should be reserved for emergency recovery.

The response is an acknowledgement, not terminal truth:

{
"ok": true,
"accepted": true,
"cancelledOrders": 1,
"operation": "cancel_all_by_market_book_side",
"ackIsTerminalState": false,
"reconciliation": {
"terminalTruth": "private_stream_dropcopy_receipts_or_account_reads",
"nextAction": "wait_for_cancel_reports_then_seed_fresh_quote_family"
}
}

After the ACK, wait for private stream, FIX/BSL drop-copy, receipts, or account order reads to confirm terminal cancel state before assuming the book is clean.

Legacy facade

The legacy-compatible HTTP facade remains available:

POST /api/v1/mm/orders/replace
POST /api/v1/mm/orders/cancel-replace

It accepts a cancelOrderId, replacement order, optional signatures, mode, time-in-force, STP, and advanced flags. It exists for clients already wired to the earlier compatibility facade. New quote engines should use signed BSL action batches.

Replaceable fields

FieldReplaceableNotes
PriceYesMust satisfy tick size
QuantityYesMust satisfy lot size and collateral checks
Time-in-forceLimitedSome transitions require cancel and new order
SideNoUse cancel and new order
MarketNoUse cancel and new order
AccountNoUse cancel and new order

Failure behavior

If the replacement is rejected, the original order remains active unless the terminal response or drop-copy event explicitly says the original order has been cancelled. Clients must reconcile final order state before updating local strategy state.

FIX and binary equivalents

  • FIX uses OrderCancelReplaceRequest (35=G).
  • BSL compact order entry uses QuoteReplace or SpotQuoteReplace.
  • Legacy HTTP uses the compatibility cancel-replace endpoint in the API reference.