X-Api-Key with trades:create; cancel and replace require
trades:execute. Send a UUID Idempotency-Key for direct order creation,
cancellation, and replacement. Quote acceptance uses the quote ID instead. Matching is
asynchronous. Consume
exchange webhooks or private WebSocket topics for timely changes, and use order
reads for recovery, operator lookups, and periodic reconciliation.
Before You Place an Order
Perform these checks in your own system before sending the request:- Fetch
GET /partner/exchange/marketsand confirm the pair is listed. - Validate
side,order_type,quantity, andpriceagainsttick_size,min_base_lot, andmin_notional. - Confirm available balance with
GET /partner/wallets/balances/overview. Creation does not check balance; an unfunded order is accepted and later reported asrejected. - Generate and store a UUID
Idempotency-Keyand a uniqueclient_order_idfor this exact order intent. - Configure exchange webhooks or private WebSocket topics before submission.
Request Fields
Unknown fields are rejected.
POST_ONLY cancels the order instead of taking
liquidity when it would cross the book.
Create A Limit Order
Limit orders specify the maximum buy price or minimum sell price you are willing to accept.Create And Accept A Quote
Create a quote withtrades:view:
quote_id, expires_at, estimated pricing and fees, and
protected_limit_price: the highest buy price or lowest sell price allowed.
Quotes expire after 30 seconds; use the returned expires_at for your countdown.
business_bps is an optional display spread, added for buys and subtracted for
sells. It does not change execution or Stabyl fees. Fees are estimates until the
order is accepted for execution.
Accept with trades:create, no body, and no Idempotency-Key:
quote_id, order_id, status: "pending", and
accepted_at. Check the returned order for the final result. Liquidity is not
reserved: fills may be partial or zero, and any unfilled remainder is cancelled.
Retry an uncertain acceptance with the same quote ID, including after expiry
if acceptance had already begun. An expired, unaccepted quote returns 409;
request a fresh quote. Unknown or another account’s quotes return 404.
Do not also submit a separate order for the same quote.
POST /partner/exchange/orders/estimate is deprecated. It remains supported with
the same request and response; use /partner/exchange/quotes for new integrations.Create A Market Order
To submit a market order directly, use/partner/exchange/orders. This does not
accept a quote or use its protected price.
Direct Order Response
The response confirms that Stabyl accepted the order request for processing. It does not mean the order is already filled.order_id. Use it for all later reads, cancels, replacements, and reconciliation. The response does not echo the order fields; read the order or wait for exchange.accepted to see them.
List Orders By Status
status (pending, accepted, partially_filled, filled, cancelled, rejected, expired), pair_id, limit (default 50, maximum 100), and offset. An unrecognised status value is ignored rather than rejected. The response contains orders and count for the page; there is no cursor or total. Use list filters for dashboards and background reconciliation. For a single order, prefer the detail endpoint, which also returns the order’s fills.
Get Order Detail
Cancel Order
{ "order_id", "status": "cancelling", "cancelled_at" }. Cancel is accepted only while the order is pending, accepted, or partially_filled; any other status returns 400. It is best effort for open quantity: if part of the order has already executed, the filled portion remains final and only remaining quantity can be cancelled. Confirm the outcome from exchange.cancelled or an order read.
Replace Order
limit orders in accepted or partially_filled status; a pending or market order returns 400. Send at least one of price or quantity. Omitting quantity keeps the remaining unfilled quantity, and an optional client_order_id names the replacement. The response is { "original_order_id", "new_order_id", "status": "replacing", "replaced_at" }. Store new_order_id: the original is cancelled and the replacement continues under the new ID. Always read the returned order and do not assume the original order is still active.
Status Handling
cancelling and replacing appear only in the cancel and replace responses
while the change is being applied; the order itself then moves to cancelled
or is superseded by the replacement.
Retry Rules
These rules apply to direct order requests. For quote acceptance, retry the same quote ID as described above.
Order writes return
400 for an invalid pair, price, quantity, or status
transition, 401, 403, 404 for an unknown or foreign order, 429, and
503. They never return 409. Insufficient balance is not a write-time
failure; it surfaces later as a rejected order.