Skip to main content
Order routes automate trading activity for your Stabyl account. Order creation requires 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:
  1. Fetch GET /partner/exchange/markets and confirm the pair is listed.
  2. Validate side, order_type, quantity, and price against tick_size, min_base_lot, and min_notional.
  3. Confirm available balance with GET /partner/wallets/balances/overview. Creation does not check balance; an unfunded order is accepted and later reported as rejected.
  4. Generate and store a UUID Idempotency-Key and a unique client_order_id for this exact order intent.
  5. 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 with trades:view:
The response includes 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:
The response contains 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.
Store the returned 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

Filters are 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

The response is { "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

Replace applies to live 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.