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

# Order Status Updates

> Real-time order status updates via WebSocket

# WebSocket: Order Status Updates

Get instant order status updates pushed to your application in real-time instead of polling the REST API.

## Connection

```
wss://partner-api.houdiniswap.com/v2/ws
```

### Authentication

Include your API credentials in the `Authorization` header during the WebSocket handshake:

```
Authorization: {partnerId}:{secret}
```

The server performs a quick format check on the header before upgrading the connection. If the header is missing or malformed, the connection is rejected at the HTTP level:

| HTTP Code | Reason |
| - | - |
| 401 | Missing `Authorization` header |
| 400 | Malformed header (must be `partnerId:secret`) |

Once the WebSocket connection is established, the server verifies your credentials asynchronously. On success you receive a `welcome` message. If credentials are invalid, you receive an `error` message with code `AUTH_FAILED` and the connection is closed with WebSocket close code `4401`.

## Quick Start

```javascript Node.js theme={null}
// Note: Custom headers require a Node.js WebSocket client (e.g. 'ws' npm package).
// Browser-native WebSocket does not support custom headers.
const WebSocket = require("ws");
const ws = new WebSocket("wss://partner-api.houdiniswap.com/v2/ws", {
  headers: { Authorization: "your-partner-id:your-secret" },
});

ws.onopen = () => {
  // Subscribe to all your orders
  ws.send(JSON.stringify({ type: "subscribe" }));
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);

  switch (message.type) {
    case "welcome":
      console.log("Connected as", message.partnerId);
      break;
    case "order_update":
      console.log("Order updated:", message.data.houdiniId, "→", message.data.status);
      break;
    case "subscribed":
      console.log("Subscribed to:", message.houdiniIds);
      break;
  }
};
```

```python Python theme={null}
import asyncio
import json
import websockets

async def listen():
    headers = {"Authorization": "your-partner-id:your-secret"}
    async with websockets.connect(
        "wss://partner-api.houdiniswap.com/v2/ws",
        additional_headers=headers,
    ) as ws:
        # Subscribe to all orders
        await ws.send(json.dumps({"type": "subscribe"}))

        async for raw in ws:
            message = json.loads(raw)
            if message["type"] == "order_update":
                data = message["data"]
                print(f"Order {data['houdiniId']} → status {data['status']}")

asyncio.run(listen())
```

```bash wscat theme={null}
wscat -H "Authorization: your-partner-id:your-secret" \
  -c wss://partner-api.houdiniswap.com/v2/ws

# Once connected, subscribe to all orders:
> {"type":"subscribe"}
```

## Message Protocol

All messages are JSON objects with a `type` field.

### Client → Server

#### subscribe

Subscribe to order status updates. Send without `houdiniIds` to receive updates for **all** your orders, or specify an array to watch specific orders.

```json Subscribe to all orders theme={null}
{ "type": "subscribe" }
```

```json Subscribe to specific orders theme={null}
{
  "type": "subscribe",
  "houdiniIds": ["abc123", "def456"]
}
```

> [!NOTE]
>
> Subscriptions are additive. Sending multiple `subscribe` messages with different `houdiniIds` adds to your watch list. Sending a `subscribe` without `houdiniIds` switches to all-orders mode.

#### unsubscribe

Stop receiving updates. Send without `houdiniIds` to unsubscribe from everything, or specify an array to stop watching specific orders.

```json Unsubscribe from all theme={null}
{ "type": "unsubscribe" }
```

```json Unsubscribe from specific orders theme={null}
{
  "type": "unsubscribe",
  "houdiniIds": ["abc123"]
}
```

> [!NOTE]
>
> If you are subscribed to all orders and send an `unsubscribe` with specific `houdiniIds`, this resets your subscription to none. To continue receiving updates for other orders, re-subscribe after unsubscribing.

#### ping

Application-level keepalive. The server responds with `pong`.

```json theme={null}
{ "type": "ping" }
```

> [!TIP]
>
> The server also sends WebSocket-level pings every 30 seconds. Most WebSocket libraries handle these automatically. The application-level `ping`/`pong` is optional — use it if you want to measure round-trip latency.

### Server → Client

#### welcome

Sent immediately after a successful connection.

```json theme={null}
{
  "type": "welcome",
  "partnerId": "your-partner-id"
}
```

#### order\_update

Pushed whenever an order's status changes. The `data` field contains the full order object — the same shape as `GET /v2/orders/{houdiniId}`.

```json theme={null}
{
  "type": "order_update",
  "data": {
    "houdiniId": "abc123",
    "status": 2,
    "inStatus": 3,
    "outStatus": null,
    "amount": "0.5",
    "amountTo": "150.25",
    "inToken": {
      "symbol": "ETH",
      "network": "ethereum"
    },
    "outToken": {
      "symbol": "USDC",
      "network": "ethereum"
    },
    "receiverAddress": "0x...",
    "created": "2026-01-15T10:30:00.000Z",
    "expires": "2026-01-15T11:00:00.000Z"
  }
}
```

#### subscribed

Confirmation after a `subscribe` message.

```json theme={null}
{
  "type": "subscribed",
  "houdiniIds": ["abc123", "def456"]
}
```

```json When subscribed to all orders theme={null}
{
  "type": "subscribed",
  "houdiniIds": "all"
}
```

#### unsubscribed

Confirmation after an `unsubscribe` message.

```json When unsubscribed from all theme={null}
{
  "type": "unsubscribed",
  "houdiniIds": "all"
}
```

```json When unsubscribed from specific orders theme={null}
{
  "type": "unsubscribed",
  "houdiniIds": ["abc123"]
}
```

#### error

Sent when the server cannot process a client message.

```json theme={null}
{
  "type": "error",
  "code": "INVALID_MESSAGE",
  "message": "Invalid JSON"
}
```

| Error Code | Description |
| - | - |
| `AUTH_FAILED` | Invalid credentials — connection will be closed with code `4401` |
| `INVALID_MESSAGE` | Message is not valid JSON or missing `type` field |
| `UNKNOWN_MESSAGE_TYPE` | The `type` field is not recognized |

## Order Status Codes

The `status` field in `order_update` is a numeric code:

| Code | Label | Description |
| - | - | - |
| -2 | INITIALIZING | Order is being initialized |
| -1 | NEW | Order initialized, awaiting processing |
| 0 | WAITING | Waiting for user's deposit |
| 1 | CONFIRMING | Deposit is being confirmed on-chain |
| 2 | EXCHANGING | Swap is in progress |
| 3 | ANONYMIZING | Going through privacy routing |
| 4 | FINISHED | Completed successfully |
| 5 | EXPIRED | Expired (no deposit within 30 minutes) |
| 6 | FAILED | Failed |
| 7 | REFUNDED | Refunded to sender |
| 8 | DELETED | Deleted (order older than 48 hours) |

**Terminal statuses** (no further updates): `FINISHED`, `EXPIRED`, `FAILED`, `REFUNDED`, `DELETED`.

## Reconnection

The server does not persist subscriptions across disconnects. If your connection drops:

1. Reconnect with credentials
2. Re-send your `subscribe` message
3. Optionally call `GET /v2/orders` to catch any updates you missed

**Recommended strategy**: exponential backoff starting at 1 second, capped at 30 seconds.

```javascript theme={null}
let reconnectDelay = 1000;

const connect = () => {
  const ws = new WebSocket(url, { headers });

  ws.onopen = () => {
    reconnectDelay = 1000; // Reset on successful connection
    ws.send(JSON.stringify({ type: "subscribe" }));
  };

  ws.onclose = () => {
    setTimeout(connect, reconnectDelay);
    reconnectDelay = Math.min(reconnectDelay * 2, 30000);
  };
};

connect();
```

## Security Notes

* Only orders belonging to your partner account are delivered. You cannot receive updates for other partners' orders.
* The `Authorization` header format is validated during the HTTP upgrade. Credentials are verified immediately after the WebSocket connection is established.
* Anonymous/private swap orders have their routing path censored from the response.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.