Cancel a single order
POST /api/orders/cancel
X-Api-Key: ps_live_<keyId>_<secret> # needs `orders:write` scope
Content-Type: application/json
{ "orderId": "0x..." }
Response:
{ "orderId": "0x...", "status": "CANCELLED", "remainingQty": "42" }
If the order already reached a terminal state before your cancel
arrived:
{ "orderId": "0x...", "status": "not_found" }
Field-name conventions across the orders API:
- The cancel request and response use
orderId.
- List/read endpoints (
GET /api/orders/open, /api/orders/history,
/api/orders/{id}) return the same value under id.
- The unfilled remainder is
remainingQty everywhere it surfaces
(cancel response, order list/read).
Treat orderId and id as the same identifier for lookup; the
variance is purely a request-vs-response convention.
Cancel all your open orders
POST /api/orders/cancel-all
X-Api-Key: ps_live_<keyId>_<secret> # needs `orders:write` scope
Content-Type: application/json
{ "marketId": "UAE-CUP-FINAL-20260425" }
Omit marketId to cancel every open order for the authenticated
wallet (authenticated associatedWallet or the API-key’s associatedWallet).
Response:
{ "cancelled": 17, "marketId": "UAE-CUP-FINAL-20260425" }
Scope filters — marketId, side, outcome
All three are optional and combine freely. Empty body = wallet-wide cancel.
| Field | Type | Effect |
|---|
marketId | string | Cancel only orders for this market symbol |
side | "buy" / "sell" (case-insensitive) | Cancel only buys or only sells |
outcome | integer ≥ 0 | Cancel only orders for this outcome index (0 / 1 / …) |
POST /api/orders/cancel-all
{ "marketId": "UAE-CUP-FINAL-20260425", "side": "sell", "outcome": 0 }
Combines into one round-trip what previously required iterating
/api/orders/open client-side and firing N cancel calls. Common
MM use case: a price spike on outcome 0 means “pull all my asks on
outcome 0 of this one market” without touching outcome-1 asks or any
buys — single call.
Cancel-all is rate-limited at 1 req/sec/wallet. Use for
operational interventions, not normal per-order cleanup.
Under the hood
- Server calls
matcher.cancelOrder over gRPC. NOT_FOUND is
treated as idempotent success.
- PG authoritative flip in a single tx:
UPDATE orders SET status='CANCELLED' WHERE id=$1 AND status IN ('PENDING','OPEN','PARTIAL')
refundResidualLocked() — sums remaining locked, refunds to available.
- Double-cancel protection via the conditional WHERE.
Cancellation states
| Condition | Final status | Notes |
|---|
Order was OPEN or PARTIAL | CANCELLED | Residual refunded |
Order was FILLED | not_found from API | Terminal — nothing to cancel |
Order was already CANCELLED | not_found from API | Idempotent |
Market was RESOLVED / CANCELLED | CANCELLED_BY_RESOLVE (set by platform) | Your DELETE returns not_found |