# Orders, idempotency, and retries ## Order flow The normal flow for one order is: 1. Send `POST /trading/accounts/{account_id}/orders` with a new `Idempotency-Key` and `client_order_id`. 2. Read the `201` response. It confirms command acceptance and contains the platform-generated `order_id` and the supplied `client_order_id`. It does not mean the order is resting or filled. 3. Receive `order_update` frames from `/orders`. Each frame contains the full order view, including `status`, `filled_qty`, and `status_reason`. 4. Treat `FILLED`, `CANCELLED`, `EXPIRED`, and `REJECTED` as terminal states. Request-body rules: | Type | Side | `price` | `qty` | `volume` | | --- | --- | --- | --- | --- | | `LIMIT` | any | required | required | forbidden | | `MARKET` | `BUY` | forbidden | forbidden | required budget | | `MARKET` | `SELL` | forbidden | required | forbidden | - `token` is required. `BUY NO` executes as `SELL YES`, and `SELL NO` executes as `BUY YES`; the matching engine uses one book of `YES` contracts. - Keep `client_order_id` unique among active orders. Reusing old values makes client-ID targeting ambiguous, so the safest policy is never to reuse them. An amend does not change the ID. - Amend and cancel identify an order by `order_id` or `client_order_id` and require `market_id` in the body. Prefer `order_id`. - Changing price or increasing quantity loses queue priority. Decreasing quantity at the same price preserves it. - A command can be accepted by REST and later rejected by the engine. Rejected amend and cancel commands arrive as `order_reject` frames. - `DELETE /trading/markets/{market_id}/orders` cancels the broker's resting orders on that market across all accounts. It returns `ref_id`; each resulting cancellation has the same value in `last_cmd_id_hex`. ## Idempotency and retries Every state-changing `POST`, `PATCH`, and `DELETE` requires an `Idempotency-Key`. 1. Generate a key for each logical command. 2. Persist the key and exact request before sending it. 3. On a timeout or retryable `5xx`, resend the same request with the same key. 4. Never reuse the key with different content. Interpret success codes according to the operation contract: - `200` or `201` normally means first acceptance for order commands. - `202` means an idempotent replay for order commands, but it is also the normal first-acceptance response for `POST .../merge`. Do not infer replay from the status code alone. - A successful command response confirms acceptance, not final execution. Important errors: - `400`, `404`, or `422`: the request, identifier, or current resource state is invalid for that operation. Fix or reconcile before retrying. - `403`: the broker is not permitted to perform the operation. - `409 idempotency_key_mismatch`: the key was reused with different content. This is a client bug; do not retry. - `429`: wait for `Retry-After`. Repeating an already recorded command with the same key and content does not consume command quota. - `503 outcome_unknown`: the safe retry period has passed. Stop retrying the command and reconcile its resource state. - Other retryable `5xx`: use bounded backoff and preserve the same key and request bytes. Idempotency context has a sliding TTL of one hour from the latest request carrying that key. Every repeat refreshes the TTL, including a payload mismatch. Do not treat expiration as permission to submit the logical command again.