> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stabyl.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket Order Commands

> Submit order create, cancel, and replace commands over WebSocket.

WebSocket order commands are useful when your service already keeps a live trading connection open. They follow the same business rules as REST order routes, but the response model is streaming oriented:

1. Send a `command` message with a unique `request_id`.
2. Receive `command_ack` or `command_error`.
3. Track final order status through `user.orders` or REST order reads.

<Warning>
  `command_ack` means the command was accepted for processing. It does not mean
  the order is filled, cancelled, or replaced. Use `user.orders` and `GET
      /partner/exchange/orders/{order_id}` for canonical status.
</Warning>

## Required Access

| Action                | Access requirement                  |
| --------------------- | ----------------------------------- |
| `order_create`        | API key enabled for order creation  |
| `order_cancel`        | API key enabled for order execution |
| `order_replace`       | API key enabled for order execution |
| `user.orders` updates | API key enabled for exchange reads  |
| `user.fills` updates  | API key enabled for exchange reads  |

## Command Envelope

Every command uses the same outer shape:

```json theme={null}
{
  "type": "command",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "action": "order_create"
}
```

Use `request_id` as your local correlation ID. If `idempotency_key` is omitted, Stabyl uses `request_id` as the idempotency key. For clarity, production clients should send both values and store them before sending the command.

## Create Order

Use the REST pair ID in command payloads. For the currently supported pair, send `USD/NGN`; topic keys such as `USD_NGN` are only used in subscription topic names.

```json theme={null}
{
  "type": "command",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "action": "order_create",
  "pair_id": "USD/NGN",
  "side": "buy",
  "order_type": "limit",
  "quantity": "100.00",
  "price": "1650.00",
  "time_in_force": "GTC",
  "client_order_id": "cli-123",
  "idempotency_key": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b"
}
```

Acknowledgement:

```json theme={null}
{
  "type": "command_ack",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "action": "order_create",
  "data": {
    "order_id": "123e4567-e89b-12d3-a456-426614174000",
    "status": "pending",
    "created_at": "2026-01-14T10:30:00Z"
  }
}
```

## Cancel Order

```json theme={null}
{
  "type": "command",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91c",
  "action": "order_cancel",
  "pair_id": "USD/NGN",
  "order_id": "123e4567-e89b-12d3-a456-426614174000",
  "idempotency_key": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91c"
}
```

Acknowledgement:

```json theme={null}
{
  "type": "command_ack",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91c",
  "action": "order_cancel",
  "data": {
    "order_id": "123e4567-e89b-12d3-a456-426614174000",
    "status": "cancelling",
    "cancelled_at": "2026-01-14T10:31:00Z"
  }
}
```

## Replace Order

```json theme={null}
{
  "type": "command",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91d",
  "action": "order_replace",
  "pair_id": "USD/NGN",
  "order_id": "123e4567-e89b-12d3-a456-426614174000",
  "quantity": "150.00",
  "price": "1655.00",
  "client_order_id": "cli-456",
  "idempotency_key": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91d"
}
```

Acknowledgement:

```json theme={null}
{
  "type": "command_ack",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91d",
  "action": "order_replace",
  "data": {
    "original_order_id": "123e4567-e89b-12d3-a456-426614174000",
    "new_order_id": "123e4567-e89b-12d3-a456-426614174111",
    "status": "replacing",
    "replaced_at": "2026-01-14T10:31:00Z"
  }
}
```

## Command Errors

Command rejections use `command_error`.

```json theme={null}
{
  "type": "command_error",
  "request_id": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "code": "VALIDATION_FAILED",
  "message": "limit orders require a price"
}
```

Common error classes:

| Code                | Meaning                                      | Action                                           |
| ------------------- | -------------------------------------------- | ------------------------------------------------ |
| `UNAUTHORIZED`      | The connection is not authenticated          | Reconnect with a valid API key                   |
| `FORBIDDEN`         | The API key is not permitted for the action  | Use a key enabled for that action                |
| `VALIDATION_FAILED` | The command payload is invalid               | Correct the command before retrying              |
| `CONFLICT`          | The idempotency key or order state conflicts | Read the order state before sending a new intent |
| `RATE_LIMITED`      | Too many messages or commands                | Back off and retry later                         |

## Production Pattern

1. Subscribe to `user.orders` before submitting commands.
2. Store `{request_id, idempotency_key, action, local_order_intent}` before sending.
3. Treat `command_ack` as asynchronous acceptance.
4. Reconcile final status from `user.orders`.
5. If the socket disconnects after a command, reconnect, resubscribe with `resume`, and read the order by REST before sending a replacement intent.
