{
  "asyncapi": "3.0.0",
  "info": {
    "title": "Polymarket Perps WebSocket API",
    "version": "1.0.0",
    "description": "WebSocket API for real-time trading operations and market data.",
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    }
  },
  "defaultContentType": "application/json",
  "servers": {
    "production": {
      "host": "ws.perpetuals.polymarket.com",
      "protocol": "wss",
      "description": "Production WebSocket server"
    }
  },
  "channels": {
    "ping": {
      "address": "/v1/ws",
      "title": "Ping",
      "summary": "Ping/pong heartbeat",
      "description": "Connections are automatically closed after 60 seconds of inactivity. Send a ping message periodically to keep the connection alive.",
      "messages": {
        "Request": {
          "name": "PingRequest",
          "title": "Ping",
          "summary": "Client sends ping to test connection and keep alive",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["ping"]
                  }
                }
              }
            },
            "required": ["req", "op"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "ping"
                }
              }
            }
          ]
        },
        "Response": {
          "name": "PongResponse",
          "title": "Pong",
          "summary": "Server responds with pong including connection info",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "object",
                "required": ["status", "ts", "sq"],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": ["ok", "err"],
                    "description": "Result status"
                  },
                  "ts": {
                    "type": "integer",
                    "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                    "example": 1767225600000
                  },
                  "sq": {
                    "type": "integer",
                    "description": "Sequence number",
                    "example": 1234567890
                  }
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Response Example",
              "payload": {
                "data": {
                  "status": "ok",
                  "ts": 1767225600000,
                  "sq": 1234567890
                }
              }
            }
          ]
        }
      }
    },
    "placeOrders": {
      "address": "/v1/ws",
      "title": "Create Orders",
      "summary": "Create new orders.",
      "description": "Create new orders.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **1 / order**</Badge>\n",
      "messages": {
        "Request": {
          "name": "PlaceOrdersRequest",
          "title": "Create Orders Request",
          "summary": "Client submits a signed order placement request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["createOrders"]
                  },
                  "args": {
                    "description": "Array of orders to create",
                    "type": "object",
                    "required": ["iid", "buy", "qty"],
                    "properties": {
                      "iid": {
                        "type": "integer",
                        "description": "Instrument ID",
                        "example": 1
                      },
                      "buy": {
                        "type": "boolean",
                        "description": "Is buy",
                        "example": true
                      },
                      "p": {
                        "type": "string",
                        "description": "Price",
                        "example": "100.00"
                      },
                      "qty": {
                        "type": "string",
                        "description": "Quantity in no. of contracts",
                        "example": "10.00"
                      },
                      "tif": {
                        "type": "string",
                        "description": "Time in force",
                        "enum": ["gtc", "ioc", "fok"]
                      },
                      "po": {
                        "type": "boolean",
                        "description": "Post only",
                        "default": false,
                        "example": false
                      },
                      "ro": {
                        "type": "boolean",
                        "description": "Reduce only",
                        "example": false,
                        "default": false
                      },
                      "c": {
                        "type": "string",
                        "description": "Client order ID",
                        "minLength": 32,
                        "maxLength": 32,
                        "pattern": "^[0-9a-f]{32}$",
                        "example": "550e8400e29b41d4a716446655440000"
                      },
                      "tr": {
                        "type": "object",
                        "description": "Optional trigger attached to this order.",
                        "properties": {
                          "market": {
                            "type": "boolean",
                            "description": "Whether the trigger executes as a market order"
                          },
                          "trp": {
                            "type": "string",
                            "description": "Trigger price",
                            "example": "110.00"
                          },
                          "tpsl": {
                            "type": "string",
                            "description": "Trigger type",
                            "enum": ["tp", "sl"]
                          }
                        }
                      },
                      "builder": {
                        "type": "object",
                        "description": "Saved builder terms. Address is the registered Perps account, and fee_rate is an additional fraction of executed notional. Terms survive approval revocation for existing orders.",
                        "required": ["address", "fee_rate"],
                        "properties": {
                          "address": {
                            "type": "string",
                            "description": "Address",
                            "example": "0x1234567890abcdef1234567890abcdef12345678"
                          },
                          "fee_rate": {
                            "type": "string",
                            "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                            "example": "0.001"
                          }
                        }
                      }
                    }
                  },
                  "grp": {
                    "type": "string",
                    "description": "TPSL grouping",
                    "enum": ["order", "position"]
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "exp": {
                "type": "integer",
                "description": "Command-processing deadline in Unix milliseconds, not an order auto-cancel time; the server caps it at now + 5 s, clamps larger values to that cap, and uses that 5 s default when omitted. Values at or before the server's clock are rejected with HTTP 400 (command expired).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "createOrders",
                  "args": [
                    {
                      "iid": 1,
                      "buy": true,
                      "p": "100.00",
                      "qty": "10.00",
                      "tif": "gtc",
                      "po": false,
                      "ro": false,
                      "c": "550e8400e29b41d4a716446655440000",
                      "tr": {
                        "trp": "110.00",
                        "tpsl": "tp"
                      },
                      "builder": {
                        "address": "0x1234567890abcdef1234567890abcdef12345678",
                        "fee_rate": "0.001"
                      }
                    }
                  ],
                  "grp": "order"
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000,
                "exp": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "PlaceOrdersResponse",
          "title": "Create Orders Response",
          "summary": "Server responds with order ACK for each submitted order",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "array",
                "description": "Array of order results",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status", "oid", "ts"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "ts": {
                          "description": "Sequenced order decision timestamp in Unix milliseconds.",
                          "type": "integer",
                          "example": 1767225600000
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "builder": {
                          "type": "object",
                          "description": "Saved builder terms. Address is the registered Perps account, and fee_rate is an additional fraction of executed notional. Terms survive approval revocation for existing orders.",
                          "required": ["address", "fee_rate"],
                          "properties": {
                            "address": {
                              "type": "string",
                              "description": "Address",
                              "example": "0x1234567890abcdef1234567890abcdef12345678"
                            },
                            "fee_rate": {
                              "type": "string",
                              "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                              "example": "0.001"
                            }
                          }
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `unauthorized`, `not_found`. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "description": "Server rejection timestamp in Unix milliseconds.",
                          "type": "integer",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Order accepted",
              "payload": {
                "id": 1,
                "data": [
                  {
                    "status": "ok",
                    "oid": 1234567890
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "cancelOrders": {
      "address": "/v1/ws",
      "title": "Cancel Orders",
      "summary": "Cancel orders.",
      "description": "Cancel orders.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **0**</Badge>\n",
      "messages": {
        "Request": {
          "name": "CancelOrdersRequest",
          "title": "Cancel Orders Request",
          "summary": "Client submits a signed order cancellation request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["cancelOrders"]
                  },
                  "args": {
                    "type": "array",
                    "description": "Array of order IDs to cancel. Cancelling an order that has attached\ntake-profit / stop-loss children (see `CreateOrder.tr`) cascades to\nthose children — they are cancelled with reason `ParentCancelled`.\n",
                    "items": {
                      "type": "integer",
                      "description": "Order ID",
                      "example": 1234567890
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "exp": {
                "type": "integer",
                "description": "Command-processing deadline in Unix milliseconds, not an order auto-cancel time; the server caps it at now + 5 s, clamps larger values to that cap, and uses that 5 s default when omitted. Values at or before the server's clock are rejected with HTTP 400 (command expired).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "cancelOrders",
                  "args": [1234567890]
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000,
                "exp": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "CancelOrdersResponse",
          "title": "Cancel Orders Response",
          "summary": "Server responds with cancel result for each order",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "array",
                "description": "Array of cancel results. A request-level failure is returned as\na single rejected item.\n",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status", "oid", "ts"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "ts": {
                          "type": "integer",
                          "description": "The time when the exchange decided this cancellation outcome, in Unix milliseconds. Sequenced outcomes use the exchange event time. Rejections created before sequencing use the gateway’s decision time. This is not the client request timestamp.",
                          "example": 1767225600000
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error", "ts"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "ts": {
                          "type": "integer",
                          "description": "The time when the exchange decided this cancellation outcome, in Unix milliseconds. Sequenced outcomes use the exchange event time. Rejections created before sequencing use the gateway’s decision time. This is not the client request timestamp.",
                          "example": 1767225600000
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Both canceled",
              "payload": {
                "id": 3,
                "data": [
                  {
                    "status": "ok",
                    "oid": 1234567890,
                    "ts": 1767225600100
                  },
                  {
                    "status": "ok",
                    "oid": 1234567891,
                    "ts": 1767225600101
                  }
                ]
              }
            },
            {
              "name": "Request rejected",
              "payload": {
                "id": 3,
                "data": [
                  {
                    "status": "err",
                    "error": "message_rate_limited",
                    "ts": 1767225600102
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "cancelOrdersCOID": {
      "address": "/v1/ws",
      "title": "Cancel Orders COID",
      "summary": "Cancel orders by client order ID.",
      "description": "Cancel orders by client order ID.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **0**</Badge>\n",
      "messages": {
        "Request": {
          "name": "CancelOrdersCoidRequest",
          "title": "Cancel Orders COID Request",
          "summary": "Client submits a signed cancel-by-client-order-id request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["cancelOrdersCOID"]
                  },
                  "args": {
                    "type": "array",
                    "description": "Array of client order IDs to cancel. Cancelling an order that has\nattached take-profit / stop-loss children (see `CreateOrder.tr`)\ncascades to those children — they are cancelled with reason\n`ParentCancelled`.\n",
                    "items": {
                      "type": "string",
                      "description": "Client order ID",
                      "minLength": 32,
                      "maxLength": 32,
                      "pattern": "^[0-9a-f]{32}$",
                      "example": "550e8400e29b41d4a716446655440000"
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "exp": {
                "type": "integer",
                "description": "Command-processing deadline in Unix milliseconds, not an order auto-cancel time; the server caps it at now + 5 s, clamps larger values to that cap, and uses that 5 s default when omitted. Values at or before the server's clock are rejected with HTTP 400 (command expired).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "cancelOrdersCOID",
                  "args": ["550e8400e29b41d4a716446655440000"]
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000,
                "exp": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "CancelOrdersCoidResponse",
          "title": "Cancel Orders COID Response",
          "summary": "Server responds with cancel result for each client order ID",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "array",
                "description": "Array of cancel results. A request-level failure is returned as\na single rejected item.\n",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status", "oid", "ts"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "ts": {
                          "type": "integer",
                          "description": "The time when the exchange decided this cancellation outcome, in Unix milliseconds. Sequenced outcomes use the exchange event time. Rejections created before sequencing use the gateway’s decision time. This is not the client request timestamp.",
                          "example": 1767225600000
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error", "ts"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "ts": {
                          "type": "integer",
                          "description": "The time when the exchange decided this cancellation outcome, in Unix milliseconds. Sequenced outcomes use the exchange event time. Rejections created before sequencing use the gateway’s decision time. This is not the client request timestamp.",
                          "example": 1767225600000
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Both canceled",
              "payload": {
                "id": 3,
                "data": [
                  {
                    "status": "ok",
                    "oid": 1234567890,
                    "coid": "550e8400e29b41d4a716446655440000",
                    "ts": 1767225600100
                  },
                  {
                    "status": "ok",
                    "oid": 1234567891,
                    "coid": "550e8400e29b41d4a716446655440001",
                    "ts": 1767225600101
                  }
                ]
              }
            },
            {
              "name": "Request rejected",
              "payload": {
                "id": 3,
                "data": [
                  {
                    "status": "err",
                    "error": "invalid_request",
                    "ts": 1767225600102
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "cancelAll": {
      "address": "/v1/ws",
      "title": "Cancel All Orders",
      "summary": "Cancel all open orders.",
      "description": "Cancel all open orders for the authenticated account, optionally scoped to\none instrument.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **0**</Badge>\n",
      "messages": {
        "Request": {
          "name": "CancelAllRequest",
          "title": "Cancel All Orders Request",
          "summary": "Client submits a signed cancel-all request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["cancelAll"]
                  },
                  "args": {
                    "type": "object",
                    "description": "Optional cancel scope. When `iid` is provided, only open orders for\nthat instrument are canceled. When omitted, all open orders for the\nsigning account are canceled.\n",
                    "properties": {
                      "iid": {
                        "type": "integer",
                        "description": "Instrument ID",
                        "example": 1
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "exp": {
                "type": "integer",
                "description": "Command-processing deadline in Unix milliseconds, not an order auto-cancel time; the server caps it at now + 5 s, clamps larger values to that cap, and uses that 5 s default when omitted. Values at or before the server's clock are rejected with HTTP 400 (command expired).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "cancelAll",
                  "args": {
                    "iid": 1
                  }
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000,
                "exp": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "CancelAllResponse",
          "title": "Cancel All Orders Response",
          "summary": "Server responds with the cancel-all result",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": ["status"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["ok"]
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": ["status", "error"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["err"]
                      },
                      "error": {
                        "type": "string",
                        "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                        "example": "insufficient_margin"
                      }
                    }
                  }
                ]
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Accepted",
              "payload": {
                "id": 5,
                "data": {
                  "status": "ok"
                }
              }
            }
          ]
        }
      }
    },
    "autoCancel": {
      "address": "/v1/ws",
      "title": "Auto-Cancel",
      "summary": "Set or clear auto-cancel dead-man-switch.",
      "description": "Arm or clear the per-account auto-cancel schedule.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **10**</Badge>\n",
      "messages": {
        "Request": {
          "name": "AutoCancelRequest",
          "title": "Auto-Cancel Request",
          "summary": "Client submits a signed auto-cancel request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["autoCancel"]
                  },
                  "args": {
                    "type": "object",
                    "required": ["time"],
                    "properties": {
                      "time": {
                        "type": "integer",
                        "description": "Timestamp in milliseconds",
                        "example": 1767225600000
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "autoCancel",
                  "args": {
                    "time": 1767225600000
                  }
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "AutoCancelResponse",
          "title": "Auto-Cancel Response",
          "summary": "Server responds with auto-cancel result",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": ["status"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["ok"]
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": ["status", "error"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["err"]
                      },
                      "error": {
                        "type": "string",
                        "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                        "example": "insufficient_margin"
                      }
                    }
                  }
                ]
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Armed",
              "payload": {
                "id": 5,
                "data": {
                  "status": "ok"
                }
              }
            }
          ]
        }
      }
    },
    "updateLeverage": {
      "address": "/v1/ws",
      "title": "Update Leverage",
      "summary": "Update leverage for an instrument.",
      "description": "Each setting resolves independently: explicit per-instrument setting, then\nexchange-managed account-group default, then instrument maximum leverage and\nisolated margin. Group leverage is capped at the instrument maximum; a group\ncross default resolves to isolated on isolated-only instruments. Group defaults\napply to new listings and never overwrite explicit settings.\nUpdating leverage sets both values explicitly. GET /v1/account/config returns\nthe resolved values. Submit the current resolved pair to preserve it against\nlater group changes. Leverage bounds and BLP locks also apply to unchanged values.\n\nSet leverage and margin type for an instrument.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **1**</Badge>\n",
      "messages": {
        "Request": {
          "name": "UpdateLeverageRequest",
          "title": "Update Leverage Request",
          "summary": "Client submits a signed leverage update request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["updateLeverage"]
                  },
                  "args": {
                    "type": "object",
                    "required": ["iid", "lev", "cross"],
                    "properties": {
                      "iid": {
                        "type": "integer",
                        "description": "Instrument ID",
                        "example": 1
                      },
                      "lev": {
                        "type": "integer",
                        "description": "Leverage",
                        "example": 10
                      },
                      "cross": {
                        "type": "boolean",
                        "description": "Whether to use cross margin mode"
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "updateLeverage",
                  "args": {
                    "iid": 1,
                    "lev": 10
                  }
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "UpdateLeverageResponse",
          "title": "Update Leverage Response",
          "summary": "Server responds with leverage update result",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": ["status"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["ok"]
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": ["status", "error"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["err"]
                      },
                      "error": {
                        "type": "string",
                        "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                        "example": "insufficient_margin"
                      }
                    }
                  }
                ]
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Updated",
              "payload": {
                "id": 6,
                "data": {
                  "status": "ok"
                }
              }
            }
          ]
        }
      }
    },
    "updateLeverages": {
      "address": "/v1/ws",
      "title": "Update Leverages",
      "summary": "Update leverage for multiple instruments.",
      "description": "Each setting resolves independently: explicit per-instrument setting, then\nexchange-managed account-group default, then instrument maximum leverage and\nisolated margin. Group leverage is capped at the instrument maximum; a group\ncross default resolves to isolated on isolated-only instruments. Group defaults\napply to new listings and never overwrite explicit settings.\nUpdating leverage sets both values explicitly. GET /v1/account/config returns\nthe resolved values. Submit the current resolved pair to preserve it against\nlater group changes. Leverage bounds and BLP locks also apply to unchanged values.\n\nUpdate leverage for up to 100 unique instruments. Updates are processed\nsequentially and are not atomic. If only some responses arrive before the\ngateway deadline, missing item results use `internal_error`; whether those\nupdates applied is unknown. If no responses arrive, the request is rejected\nwith `internal_error` instead.\nRequires proxy signature, see [Update Leverage](/perps/trading#update-leverage).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **1 / instrument**</Badge>\n",
      "messages": {
        "Request": {
          "name": "UpdateLeveragesRequest",
          "title": "Update Leverages Request",
          "summary": "Client submits a signed batch leverage update request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["updateLeverages"]
                  },
                  "args": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 100,
                    "items": {
                      "type": "object",
                      "required": ["iid", "lev", "cross"],
                      "properties": {
                        "iid": {
                          "type": "integer",
                          "description": "Instrument ID",
                          "example": 1
                        },
                        "lev": {
                          "type": "integer",
                          "description": "Leverage",
                          "example": 10
                        },
                        "cross": {
                          "type": "boolean",
                          "description": "Whether to use cross margin mode"
                        }
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "updateLeverages",
                  "args": [
                    {
                      "iid": 1,
                      "lev": 10,
                      "cross": true
                    }
                  ]
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000
              }
            }
          ]
        },
        "Response": {
          "name": "UpdateLeveragesResponse",
          "title": "Update Leverages Response",
          "summary": "Server responds with an ordered result for each instrument",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "array",
                "description": "Ordered per-instrument results. A request-level failure is\nreturned as a single rejected item without an instrument id.\n",
                "items": {
                  "anyOf": [
                    {
                      "oneOf": [
                        {
                          "description": "The instrument's effective leverage configuration after the update.",
                          "type": "object",
                          "required": [
                            "status",
                            "instrument_id",
                            "leverage",
                            "cross"
                          ],
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": ["ok"]
                            },
                            "instrument_id": {
                              "type": "integer",
                              "description": "Instrument ID",
                              "example": 1
                            },
                            "leverage": {
                              "type": "integer",
                              "description": "Leverage",
                              "example": 10
                            },
                            "cross": {
                              "type": "boolean",
                              "description": "Whether to use cross margin mode"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": ["status", "instrument_id", "error"],
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": ["err"]
                            },
                            "instrument_id": {
                              "type": "integer",
                              "description": "Instrument ID",
                              "example": 1
                            },
                            "error": {
                              "type": "string",
                              "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                              "example": "insufficient_margin"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Mixed result",
              "payload": {
                "id": 7,
                "data": [
                  {
                    "status": "ok",
                    "instrument_id": 1,
                    "leverage": 5,
                    "cross": false
                  },
                  {
                    "status": "err",
                    "instrument_id": 2,
                    "error": "insufficient_margin"
                  }
                ]
              }
            },
            {
              "name": "Request rejected",
              "payload": {
                "id": 7,
                "data": [
                  {
                    "status": "err",
                    "error": "invalid signature"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "updateMargin": {
      "address": "/v1/ws",
      "title": "Update Isolated Margin",
      "summary": "Add or remove margin from an isolated position.",
      "description": "Adjust the collateral allocated to an existing isolated position.\nPositive `amt` adds margin and negative `amt` removes it. A removal may\ninclude unrealized isolated profit, as long as the position's equity\nstays at or above its current required initial margin.\n\nThe exchange rejects both additions and removals while the account is in\ncross liquidation or the target position is in isolated liquidation. An\nisolated liquidation on another instrument does not block the request,\nand neither does cancel-only mode.\n\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\nGateway validation rejects a stale or future-skewed timestamp as\n`invalid signature`. A request that passes the gateway can still be\nrejected with `invalid_margin_signature_timestamp` if its timestamp is no\nlonger fresh when the exchange executes it. Reusing the exact signed\nrequest rejects with `signature_already_used`.\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **1**</Badge>\n",
      "messages": {
        "Request": {
          "name": "UpdateMarginRequest",
          "title": "Update Isolated Margin Request",
          "summary": "Client submits a signed isolated-margin adjustment",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["updateMargin"]
                  },
                  "args": {
                    "type": "object",
                    "required": ["iid", "amt"],
                    "properties": {
                      "iid": {
                        "type": "integer",
                        "description": "Instrument ID",
                        "example": 1
                      },
                      "amt": {
                        "type": "string",
                        "description": "Signed isolated-margin adjustment in the instrument quote asset. Positive values add allocation; negative values remove it.",
                        "example": "100.00"
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "AddMargin",
              "payload": {
                "id": 7,
                "req": "post",
                "op": {
                  "type": "updateMargin",
                  "args": {
                    "iid": 1,
                    "amt": "100.00"
                  }
                },
                "sig": "0x7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d1c",
                "salt": 444444444,
                "ts": 1767000013000
              }
            },
            {
              "name": "RemoveMargin",
              "payload": {
                "id": 8,
                "req": "post",
                "op": {
                  "type": "updateMargin",
                  "args": {
                    "iid": 1,
                    "amt": "-25.00"
                  }
                },
                "sig": "0x7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d1c",
                "salt": 444444445,
                "ts": 1767000013001
              }
            }
          ]
        },
        "Response": {
          "name": "UpdateMarginResponse",
          "title": "Update Isolated Margin Response",
          "summary": "Server responds with the margin update result",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": ["status"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["ok"]
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": ["status", "error"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["err"]
                      },
                      "error": {
                        "type": "string",
                        "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                        "example": "insufficient_margin"
                      }
                    }
                  }
                ]
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Updated",
              "payload": {
                "id": 7,
                "data": {
                  "status": "ok"
                }
              }
            },
            {
              "name": "Rejected",
              "payload": {
                "id": 8,
                "data": {
                  "status": "err",
                  "error": "margin_below_required_initial"
                }
              }
            }
          ]
        }
      }
    },
    "auth": {
      "address": "/v1/ws",
      "title": "Auth",
      "summary": "Authentication to access private channels.",
      "messages": {
        "Request": {
          "name": "AuthRequest",
          "title": "Auth",
          "summary": "Authenticate this WebSocket connection for private channels",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["auth"]
                  },
                  "args": {
                    "type": "object",
                    "required": ["proxy", "secret"],
                    "properties": {
                      "proxy": {
                        "type": "string",
                        "description": "Proxy address in hex format",
                        "example": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
                      },
                      "secret": {
                        "type": "string",
                        "description": "API secret",
                        "example": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
                      }
                    }
                  }
                }
              }
            },
            "required": ["req", "op"]
          },
          "examples": [
            {
              "name": "Request Example",
              "payload": {
                "req": "post",
                "op": {
                  "type": "auth",
                  "args": {
                    "proxy": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
                    "secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
                  }
                }
              }
            }
          ]
        },
        "Response": {
          "name": "AuthResponse",
          "title": "Auth Response",
          "summary": "Authentication result",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "oneOf": [
                  {
                    "type": "object",
                    "description": "Successful auth acknowledgement; pod is optional for compatibility during rolling deploys.",
                    "required": ["status"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["ok"]
                      },
                      "pod": {
                        "type": "string",
                        "description": "Gateway pod identity for log correlation only; pods are not addressable.",
                        "example": "gateway-ws-7b68c9d4f5-m2n8p"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": ["status", "error"],
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": ["err"]
                      },
                      "error": {
                        "type": "string",
                        "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                        "example": "insufficient_margin"
                      }
                    }
                  }
                ]
              }
            },
            "required": ["data"]
          }
        }
      }
    },
    "trades": {
      "address": "/v1/ws",
      "title": "Trades",
      "summary": "Real-time trade stream.",
      "messages": {
        "SubscribeRequest": {
          "name": "TradesSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to public trade updates for an instrument",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Trades subscription in format \"trades::{iid}\" (e.g., \"trades::1\")",
                "items": {
                  "type": "string",
                  "pattern": "^trades::\\d+$"
                },
                "example": ["trades::1"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["trades::1"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "TradesSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to trades subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "TradesUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from public trade updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Trades subscription in format \"trades::{iid}\" (e.g., \"trades::1\")",
                "items": {
                  "type": "string",
                  "pattern": "^trades::\\d+$"
                },
                "example": ["trades::1"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["trades::1"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "TradesUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to trades unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "TradesUpdate",
          "title": "Update",
          "summary": "Real-time trade updates for subscribed instruments",
          "contentType": "application/json",
          "payload": {
            "title": "Trades Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Array of trade objects",
                "title": "TradeResponse",
                "properties": {
                  "tid": {
                    "type": "integer",
                    "description": "Trade ID",
                    "example": 1
                  },
                  "iid": {
                    "type": "integer",
                    "description": "Instrument ID",
                    "example": 1
                  },
                  "side": {
                    "type": "string",
                    "description": "Side",
                    "enum": ["long", "short"]
                  },
                  "p": {
                    "type": "string",
                    "description": "Price",
                    "example": "100.00"
                  },
                  "qty": {
                    "type": "string",
                    "description": "Quantity in no. of contracts",
                    "example": "10.00"
                  },
                  "ts": {
                    "type": "integer",
                    "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                    "example": 1767225600000
                  },
                  "hash": {
                    "type": "string",
                    "description": "On-chain transaction hash, \"0x\" if not yet mined",
                    "default": "0x",
                    "example": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
                  },
                  "settlement": {
                    "type": "boolean",
                    "description": "Whether this fill closes a position during permanent instrument settlement. Settlement fills use the final settlement price and have no fees or liquidation penalties; they are not normal market trades or ADL."
                  }
                },
                "required": [
                  "tid",
                  "iid",
                  "side",
                  "p",
                  "qty",
                  "ts",
                  "settlement",
                  "hash"
                ]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "trades::1",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "tid": 1,
                    "iid": 1,
                    "side": "long",
                    "p": "100.00",
                    "qty": "10.00",
                    "ts": 1767225600000,
                    "hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "bbo": {
      "address": "/v1/ws",
      "title": "BBO",
      "summary": "Best bid and offer real-time updates.",
      "messages": {
        "SubscribeRequest": {
          "name": "BBOSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to BBO updates for a specific instrument",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "BBO subscription per instrument: `bbo::{iid}` (e.g. `bbo::1`).\n",
                "items": {
                  "type": "string",
                  "pattern": "^bbo::\\d+$"
                },
                "example": ["bbo::1"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["bbo::1"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "BBOSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to BBO subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "BBOUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from BBO updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "BBO subscription per instrument: `bbo::{iid}` (e.g. `bbo::1`).\n",
                "items": {
                  "type": "string",
                  "pattern": "^bbo::\\d+$"
                },
                "example": ["bbo::1"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["bbo::1"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "BBOUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to BBO unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "BBOUpdate",
          "title": "Update",
          "summary": "Real-time BBO updates for subscribed instruments",
          "contentType": "application/json",
          "payload": {
            "title": "BBO Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "BBO object",
                "title": "BBO Data",
                "properties": {
                  "iid": {
                    "type": "integer",
                    "description": "Instrument ID",
                    "example": 1
                  },
                  "bp": {
                    "type": "string",
                    "description": "Best bid price",
                    "example": "99.50"
                  },
                  "bq": {
                    "type": "string",
                    "description": "Best bid quantity",
                    "example": "10.00"
                  },
                  "ap": {
                    "type": "string",
                    "description": "Best ask price",
                    "example": "100.50"
                  },
                  "aq": {
                    "type": "string",
                    "description": "Best ask quantity",
                    "example": "10.00"
                  }
                },
                "required": ["iid", "bp", "bq", "ap", "aq"]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "bbo::1",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "iid": 1,
                  "bp": "99.50",
                  "bq": "10.00",
                  "ap": "100.50",
                  "aq": "10.00"
                }
              }
            }
          ]
        }
      }
    },
    "book": {
      "address": "/v1/ws",
      "title": "Book",
      "summary": "Order book snapshot updates (top 20 or, with the ::50 suffix, top 50 levels per side). Pushed every 100ms.",
      "messages": {
        "SubscribeRequest": {
          "name": "BookSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to order book updates for an instrument",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "description": "Client-supplied identifier used to correlate the response.",
                "type": "integer"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Book subscription in format \"book::{iid}\" or \"book::{iid}::{depth}\". Omitted depth and \"20\" select the top 20 levels per side; \"50\" selects the top 50. Allowed depths are exactly 20 and 50.",
                "items": {
                  "type": "string",
                  "pattern": "^book::\\d+(::(20|50))?$"
                },
                "example": ["book::1", "book::1::50"]
              }
            },
            "required": ["req", "chs"],
            "description": "Each inbound request consumes a weighted WebSocket message token. Before\nauthentication the budget is per client IP. After authentication all of\nthe account's sockets share its tier budget across IPs. The first valid\nsigned write also binds an unauthenticated socket to its recovered account.\nLater signed writes must resolve that same account. A breach returns\n`message_rate_limited` and leaves the socket open.\n\nSigned write posts carrying an `id` are dispatched concurrently (up to 16\nin flight per connection) and may execute and respond out of request\norder, matching the semantics of concurrent HTTP requests. Ordering is\nkept per connection for posts that name the same client order id or\norder id, and `cancelAll`, leverage and margin updates wait for every\nearlier post on the connection while later posts wait for them. Posts\nwithout an `id` are dispatched one at a time but are not ordered after\nearlier `id`-carrying posts still in flight. For strict ordering, await\neach response before sending the next request, or omit `id` on every\npost. Use a unique `id` for every in-flight request on a connection.\nUniqueness is not enforced and duplicate in-flight IDs are ambiguous.\n"
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["book::1", "book::1::50"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "BookSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to book subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "type": "integer",
                          "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "BookUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from order book updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "description": "Client-supplied identifier used to correlate the response.",
                "type": "integer"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Book subscription in format \"book::{iid}\" or \"book::{iid}::{depth}\". Omitted depth and \"20\" select the top 20 levels per side; \"50\" selects the top 50. Allowed depths are exactly 20 and 50.",
                "items": {
                  "type": "string",
                  "pattern": "^book::\\d+(::(20|50))?$"
                },
                "example": ["book::1", "book::1::50"]
              }
            },
            "required": ["req", "chs"],
            "description": "Each inbound request consumes a weighted WebSocket message token. Before\nauthentication the budget is per client IP. After authentication all of\nthe account's sockets share its tier budget across IPs. The first valid\nsigned write also binds an unauthenticated socket to its recovered account.\nLater signed writes must resolve that same account. A breach returns\n`message_rate_limited` and leaves the socket open.\n\nSigned write posts carrying an `id` are dispatched concurrently (up to 16\nin flight per connection) and may execute and respond out of request\norder, matching the semantics of concurrent HTTP requests. Ordering is\nkept per connection for posts that name the same client order id or\norder id, and `cancelAll`, leverage and margin updates wait for every\nearlier post on the connection while later posts wait for them. Posts\nwithout an `id` are dispatched one at a time but are not ordered after\nearlier `id`-carrying posts still in flight. For strict ordering, await\neach response before sending the next request, or omit `id` on every\npost. Use a unique `id` for every in-flight request on a connection.\nUniqueness is not enforced and duplicate in-flight IDs are ambiguous.\n"
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["book::1", "book::1::50"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "BookUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to book unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "type": "integer",
                          "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "BookUpdate",
          "title": "Update",
          "summary": "Real-time order book updates for subscribed instruments",
          "contentType": "application/json",
          "payload": {
            "title": "Book Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "description": "Server send time, Unix milliseconds",
                "type": "integer",
                "example": 1767225600000
              },
              "ets": {
                "type": "integer",
                "description": "Event timestamp — the newest event this update reflects, in Unix milliseconds. Distinct from `ts`, which is the server send time; `ts - ets` is time spent inside the exchange after the event. `ets=0` means no event horizon is attested, and consumers must treat the horizon as unknown.",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "required": ["b", "a"],
                "properties": {
                  "b": {
                    "type": "array",
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "maxItems": 2,
                      "description": "- `\"100.00\"` - Price\n- `\"10.00\"` - Quantity\n",
                      "example": ["100.00", "10.00"]
                    },
                    "description": "Bid levels"
                  },
                  "a": {
                    "type": "array",
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "maxItems": 2,
                      "description": "- `\"100.00\"` - Price\n- `\"10.00\"` - Quantity\n",
                      "example": ["100.00", "10.00"]
                    },
                    "description": "Ask levels"
                  }
                }
              }
            },
            "required": ["ch", "ts", "ets", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "book::1",
                "ts": 1767225600000,
                "ets": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "b": [["100.00", "10.00"]],
                  "a": [["100.00", "10.00"]]
                }
              }
            }
          ]
        }
      }
    },
    "klines": {
      "address": "/v1/ws",
      "title": "Klines",
      "summary": "Real-time kline updates.",
      "messages": {
        "SubscribeRequest": {
          "name": "KlinesSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to kline updates for an instrument and interval",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Klines subscription in format \"klines::{iid}::{interval}\" (e.g., \"klines::1::1m\")",
                "items": {
                  "type": "string",
                  "pattern": "^klines::\\d+::(1s|1m|5m|15m|30m|1h|4h|6h|12h|1d|1w)$"
                },
                "example": ["klines::1::1m"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["klines::1::1m"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "KlinesSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to klines subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "KlinesUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from kline updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Klines subscription in format \"klines::{iid}::{interval}\" (e.g., \"klines::1::1m\")",
                "items": {
                  "type": "string",
                  "pattern": "^klines::\\d+::(1s|1m|5m|15m|30m|1h|4h|6h|12h|1d|1w)$"
                },
                "example": ["klines::1::1m"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["klines::1::1m"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "KlinesUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to klines unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "KlineUpdate",
          "title": "Update",
          "summary": "Real-time kline updates for subscribed instruments",
          "contentType": "application/json",
          "payload": {
            "title": "Kline Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "array",
                "description": "Array of kline arrays",
                "items": {
                  "type": "array",
                  "description": "- `1767225600000` - Open time\n- `\"100.00\"` - Open price\n- `\"105.00\"` - High price\n- `\"99.00\"` - Low price\n- `\"102.00\"` - Close price\n- `\"500.00\"` - Volume (base unit)\n- `42` - Number of trades\n",
                  "example": [
                    1767225600000,
                    "100.00",
                    "105.00",
                    "99.00",
                    "102.00",
                    "500.00",
                    42
                  ]
                }
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "klines::1::1m",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": [
                  [
                    1767225600000,
                    "100.00",
                    "105.00",
                    "99.00",
                    "102.00",
                    "500.00",
                    42
                  ]
                ]
              }
            }
          ]
        }
      }
    },
    "tickers": {
      "address": "/v1/ws",
      "title": "Tickers",
      "summary": "Ticker updates. Pushed every 100ms.",
      "messages": {
        "SubscribeRequest": {
          "name": "TickersSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to ticker updates for all instruments or a specific one",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Ticker subscription: `tickers::all` for every active instrument,\nor `tickers::{iid}` (e.g. `tickers::1`) for a specific one.\n",
                "items": {
                  "type": "string",
                  "pattern": "^tickers::(\\d+|all)$"
                },
                "example": ["tickers::all"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["tickers::all"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "TickersSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to tickers subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "TickersUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from ticker updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Ticker subscription: `tickers::all` for every active instrument,\nor `tickers::{iid}` (e.g. `tickers::1`) for a specific one.\n",
                "items": {
                  "type": "string",
                  "pattern": "^tickers::(\\d+|all)$"
                },
                "example": ["tickers::all"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["tickers::all"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "TickersUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to tickers unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "TickerUpdate",
          "title": "Update",
          "summary": "Real-time ticker updates for subscribed instruments",
          "contentType": "application/json",
          "payload": {
            "title": "Ticker Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Array of ticker objects",
                "properties": {
                  "iid": {
                    "type": "integer",
                    "description": "Instrument ID",
                    "example": 1
                  },
                  "idx": {
                    "type": "string",
                    "description": "Index price",
                    "example": "100.00"
                  },
                  "mark": {
                    "type": "string",
                    "description": "Mark price",
                    "example": "100.00"
                  },
                  "last": {
                    "type": "string",
                    "description": "Last traded price",
                    "example": "100.00"
                  },
                  "mid": {
                    "type": "string",
                    "description": "Mid price",
                    "example": "100.00"
                  },
                  "oi": {
                    "type": "string",
                    "description": "Open interest in number of contracts",
                    "example": "10.00"
                  },
                  "fr": {
                    "type": "string",
                    "description": "Funding rate",
                    "example": "0.0001"
                  },
                  "nxf": {
                    "type": "integer",
                    "description": "Next funding timestamp in milliseconds",
                    "example": 1767225600000
                  }
                },
                "required": [
                  "iid",
                  "idx",
                  "mark",
                  "last",
                  "mid",
                  "oi",
                  "fr",
                  "nxf"
                ]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "tickers::all",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "iid": 1,
                    "idx": "100.00",
                    "mark": "100.00",
                    "last": "100.00",
                    "mid": "100.00",
                    "oi": "10.00",
                    "fr": "0.0001",
                    "nxf": 1767225600000
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "statistics": {
      "address": "/v1/ws",
      "title": "Statistics",
      "summary": "24-hour statistics updates. Pushed every 1 second.",
      "messages": {
        "SubscribeRequest": {
          "name": "StatisticsSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to 24-hour statistics updates for all instruments or a specific one",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Statistics subscription: `statistics::all` for every active instrument,\nor `statistics::{iid}` (e.g. `statistics::1`) for a specific one.\n",
                "items": {
                  "type": "string",
                  "pattern": "^statistics::(\\d+|all)$"
                },
                "example": ["statistics::all"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["statistics::all"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "StatisticsSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to statistics subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "StatisticsUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from statistics updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Statistics subscription: `statistics::all` for every active instrument,\nor `statistics::{iid}` (e.g. `statistics::1`) for a specific one.\n",
                "items": {
                  "type": "string",
                  "pattern": "^statistics::(\\d+|all)$"
                },
                "example": ["statistics::all"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["statistics::all"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "StatisticsUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to statistics unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "StatisticsUpdate",
          "title": "Update",
          "summary": "24-hour statistics for subscribed instruments",
          "contentType": "application/json",
          "payload": {
            "title": "Statistics Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Array of statistics objects",
                "properties": {
                  "iid": {
                    "type": "integer",
                    "description": "Instrument ID",
                    "example": 1
                  },
                  "vol": {
                    "type": "string",
                    "description": "24-hour trading volume in quote-asset notional (sum of price times quantity), as a numeric string",
                    "example": "1000.00"
                  },
                  "open": {
                    "type": "string",
                    "description": "Opening price of the earliest populated candle in the rolling 24-hour window, whose start is rounded down to the minute. Returns \"0\" when the window has no candles.",
                    "example": "100.50"
                  },
                  "klines": {
                    "type": "array",
                    "items": {
                      "type": "array",
                      "description": "- `1767225600000` - Open time\n- `\"100.00\"` - Open price\n- `\"105.00\"` - High price\n- `\"99.00\"` - Low price\n- `\"102.00\"` - Close price\n- `\"500.00\"` - Volume (base unit)\n- `42` - Number of trades\n",
                      "example": [
                        1767225600000,
                        "100.00",
                        "105.00",
                        "99.00",
                        "102.00",
                        "500.00",
                        42
                      ]
                    },
                    "description": "Last 24-hour kline data"
                  }
                },
                "required": ["iid", "vol", "open", "klines"]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "statistics::all",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "iid": 1,
                    "vol": "1000.00",
                    "open": "100.50",
                    "klines": [
                      [
                        1767225600000,
                        "100.00",
                        "105.00",
                        "99.00",
                        "102.00",
                        "500.00",
                        42
                      ]
                    ]
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "fills": {
      "address": "/v1/ws",
      "title": "Fills",
      "summary": "Real-time fill updates. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "FillsSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private fill updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Fills private channel: \"fills\"",
                "items": {
                  "type": "string",
                  "enum": ["fills"]
                },
                "example": ["fills"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["fills"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "FillsSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to fills subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "FillsUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private fill updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Fills private channel: \"fills\"",
                "items": {
                  "type": "string",
                  "enum": ["fills"]
                },
                "example": ["fills"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["fills"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "FillsUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to fills unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "FillsUpdate",
          "title": "Update",
          "summary": "Real-time fill updates for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "Fills Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "array",
                "description": "Array of fill objects",
                "items": {
                  "type": "object",
                  "required": [
                    "tid",
                    "oid",
                    "iid",
                    "side",
                    "p",
                    "qty",
                    "taker",
                    "fee",
                    "builder_fee",
                    "total_fee",
                    "fea",
                    "psz",
                    "pep",
                    "pnl",
                    "ts",
                    "settlement",
                    "liq",
                    "adl"
                  ],
                  "properties": {
                    "tid": {
                      "type": "integer",
                      "description": "Trade ID",
                      "example": 1
                    },
                    "oid": {
                      "type": "integer",
                      "description": "Order ID",
                      "example": 1234567890
                    },
                    "iid": {
                      "type": "integer",
                      "description": "Instrument ID",
                      "example": 1
                    },
                    "side": {
                      "type": "string",
                      "description": "Side",
                      "enum": ["long", "short"]
                    },
                    "p": {
                      "type": "string",
                      "description": "Price",
                      "example": "100.00"
                    },
                    "qty": {
                      "type": "string",
                      "description": "Quantity in no. of contracts",
                      "example": "10.00"
                    },
                    "taker": {
                      "type": "boolean",
                      "description": "Whether this side was the taker"
                    },
                    "fee": {
                      "type": "string",
                      "description": "Signed exchange fee for this trade side, excluding builder_fee. Negative values are rebates",
                      "example": "1.25"
                    },
                    "builder_fee": {
                      "type": "string",
                      "description": "Actual additional builder fee in the same asset as fee, floored independently for each execution to that asset's token decimals (six for pUSD), with discarded dust and no carry. The fee is non-negative and is zero for older or untagged fills and excluded forced liquidation legs.",
                      "example": "1.00"
                    },
                    "total_fee": {
                      "type": "string",
                      "description": "Exact signed sum of exchange fee and builder_fee in the same asset. May be negative when exchange rebates exceed the builder charge.",
                      "example": "2.25"
                    },
                    "builder": {
                      "type": "object",
                      "description": "Saved builder terms. Address is the registered Perps account, and fee_rate is an additional fraction of executed notional. Terms survive approval revocation for existing orders.",
                      "required": ["address", "fee_rate"],
                      "properties": {
                        "address": {
                          "type": "string",
                          "description": "Address",
                          "example": "0x1234567890abcdef1234567890abcdef12345678"
                        },
                        "fee_rate": {
                          "type": "string",
                          "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                          "example": "0.001"
                        }
                      }
                    },
                    "fea": {
                      "type": "string",
                      "description": "Fee asset name",
                      "example": "USDC"
                    },
                    "psz": {
                      "type": "string",
                      "description": "Position size before the fill",
                      "example": "26.86"
                    },
                    "pep": {
                      "type": "string",
                      "description": "Position entry price before the fill",
                      "example": "100.00"
                    },
                    "pnl": {
                      "description": "Realized trading PnL before exchange and builder fees. Subtract total_fee once to calculate this fill's net trading result.",
                      "type": "string",
                      "example": "100.00"
                    },
                    "liq": {
                      "type": "boolean",
                      "description": "Whether this fill was part of a liquidation of the account's position — true on forced closes and on any fill executed while the account was under liquidation on the instrument, maker or taker. False on the counterparty leg of an auto-deleveraging or backstop match — its fill is part of someone else's liquidation, flagged by `adl` where applicable"
                    },
                    "adl": {
                      "type": "boolean",
                      "description": "Whether the fill came from auto-deleveraging"
                    },
                    "ts": {
                      "type": "integer",
                      "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                      "example": 1767225600000
                    },
                    "settlement": {
                      "type": "boolean",
                      "description": "Whether this fill closes a position during permanent instrument settlement. Settlement fills use the final settlement price and have no fees or liquidation penalties; they are not normal market trades or ADL."
                    },
                    "coid": {
                      "type": "string",
                      "description": "Client order ID",
                      "minLength": 32,
                      "maxLength": 32,
                      "pattern": "^[0-9a-f]{32}$",
                      "example": "550e8400e29b41d4a716446655440000"
                    },
                    "liquidation_details": {
                      "type": "object",
                      "required": ["mark", "method"],
                      "properties": {
                        "liquidated_user": {
                          "type": "string",
                          "description": "Checksummed address of the liquidated account. Present on authenticated fill surfaces and, on public account-scoped routes, only on the liquidated account's own rows. It is absent on fund-side public rows and the anonymous trade tape."
                        },
                        "mark": {
                          "type": "string",
                          "description": "Mark price captured when the liquidation command was issued. The fill price itself stays the accounting price."
                        },
                        "method": {
                          "type": "string",
                          "enum": ["market", "backstop"],
                          "description": "How the position was liquidated. Only backstop is emitted today. The market value is reserved for order-book liquidations, which currently carry no liquidation_details."
                        }
                      }
                    }
                  }
                }
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "fills",
                "ts": 1767225600000,
                "ets": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "tid": 1,
                    "oid": 1234567890,
                    "iid": 1,
                    "side": "long",
                    "p": "100.00",
                    "qty": "10.00",
                    "fee": "1.25",
                    "builder_fee": "1.00",
                    "total_fee": "2.25",
                    "builder": {
                      "address": "0x1234567890abcdef1234567890abcdef12345678",
                      "fee_rate": "0.001"
                    },
                    "fea": "USDC",
                    "psz": "26.86",
                    "pep": "100.00",
                    "pnl": "100.00",
                    "ts": 1767225600000,
                    "coid": "550e8400e29b41d4a716446655440000",
                    "liquidation_details": {
                      "method": "market"
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "backstop": {
      "address": "/v1/ws",
      "title": "Backstop",
      "summary": "Real-time backstop liquidation updates. Restricted to Backstop Liquidity Provider participants; requires authentication, see [Auth](/ws/auth).",
      "description": "Emitted when the insurance fund absorbs an account's positions because a liquidation could not be filled on the book. Each frame covers one absorption: the account, the positions taken over, and the margin transferred to the fund.\nSubscription is restricted to accounts enrolled in the Backstop Liquidity Provider program. Any other account is rejected with `unauthorized`, and an account removed from the program stops receiving updates.",
      "messages": {
        "SubscribeRequest": {
          "name": "BackstopSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to backstop updates (requires prior auth and BLP enrolment)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Backstop private channel: \"backstop\"",
                "items": {
                  "type": "string",
                  "enum": ["backstop"]
                },
                "example": ["backstop"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["backstop"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "BackstopSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to backstop subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "BackstopUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from backstop updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Backstop private channel: \"backstop\"",
                "items": {
                  "type": "string",
                  "enum": ["backstop"]
                },
                "example": ["backstop"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["backstop"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "BackstopUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to backstop unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "BackstopUpdate",
          "title": "Update",
          "summary": "Real-time backstop liquidation updates for BLP participants",
          "contentType": "application/json",
          "payload": {
            "title": "Backstop Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "One absorption of an account's positions and margin by the insurance fund. A cross backstop reports every cross position on the account and sweeps its collateral once; an isolated backstop reports the single position and its isolated margin.",
                "required": ["lid", "cross", "mgn", "pos"],
                "properties": {
                  "lid": {
                    "type": "integer",
                    "description": "Liquidation ID. Identifies one absorption of an account's positions by the insurance fund. Probabilistically unique (same guarantees as trade IDs).",
                    "example": 1234567890
                  },
                  "cross": {
                    "type": "boolean",
                    "description": "Whether to use cross margin mode"
                  },
                  "mgn": {
                    "type": "string",
                    "description": "Net margin transferred to the insurance fund in USD, covering the quote asset only. Negative when the fund returned more isolated margin than the account's balance covered, i.e. it absorbed bad debt.",
                    "example": "150.00"
                  },
                  "pos": {
                    "type": "array",
                    "description": "Positions absorbed by the insurance fund",
                    "items": {
                      "type": "object",
                      "description": "One position absorbed by the insurance fund.",
                      "required": ["tid", "iid", "side", "qty", "p"],
                      "properties": {
                        "tid": {
                          "type": "integer",
                          "description": "Trade ID",
                          "example": 1
                        },
                        "iid": {
                          "type": "integer",
                          "description": "Instrument ID",
                          "example": 1
                        },
                        "side": {
                          "type": "string",
                          "description": "Side",
                          "enum": ["long", "short"]
                        },
                        "qty": {
                          "type": "string",
                          "description": "Quantity in no. of contracts",
                          "example": "10.00"
                        },
                        "p": {
                          "type": "string",
                          "description": "Price",
                          "example": "100.00"
                        }
                      }
                    }
                  }
                }
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "backstop",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "lid": 1234567890,
                  "mgn": "150.00",
                  "pos": [
                    {
                      "tid": 1,
                      "iid": 1,
                      "side": "long",
                      "qty": "10.00",
                      "p": "100.00"
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    },
    "orders": {
      "address": "/v1/ws",
      "title": "Orders",
      "summary": "Real-time order updates. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "OrdersSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private order updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Orders private channel: \"orders\"",
                "items": {
                  "type": "string",
                  "enum": ["orders"]
                },
                "example": ["orders"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["orders"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "OrdersSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to orders subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "OrdersUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private order updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Orders private channel: \"orders\"",
                "items": {
                  "type": "string",
                  "enum": ["orders"]
                },
                "example": ["orders"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["orders"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "OrdersUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to orders unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "OrdersUpdate",
          "title": "Update",
          "summary": "Real-time order updates for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "Orders Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Order object",
                "properties": {
                  "oid": {
                    "type": "integer",
                    "description": "Order ID",
                    "example": 1234567890
                  },
                  "iid": {
                    "type": "integer",
                    "description": "Instrument ID",
                    "example": 1
                  },
                  "buy": {
                    "type": "boolean",
                    "description": "Is buy",
                    "example": true
                  },
                  "p": {
                    "type": "string",
                    "description": "Price",
                    "example": "100.00"
                  },
                  "qty": {
                    "type": "string",
                    "description": "Quantity in no. of contracts",
                    "example": "10.00"
                  },
                  "tif": {
                    "type": "string",
                    "description": "Time in force",
                    "enum": ["gtc", "ioc", "fok"]
                  },
                  "po": {
                    "type": "boolean",
                    "description": "Post only",
                    "default": false,
                    "example": false
                  },
                  "ro": {
                    "type": "boolean",
                    "description": "Reduce only",
                    "example": false,
                    "default": false
                  },
                  "rest": {
                    "type": "string",
                    "description": "Resting quantity",
                    "example": "9.00"
                  },
                  "fill": {
                    "type": "string",
                    "description": "Filled quantity",
                    "example": "1.00"
                  },
                  "cts": {
                    "type": "integer",
                    "description": "Create timestamp in milliseconds",
                    "example": 1767225600000
                  },
                  "uts": {
                    "type": "integer",
                    "description": "Update timestamp in milliseconds",
                    "example": 1767225600000
                  },
                  "status": {
                    "type": "string",
                    "description": "Order status",
                    "example": "open"
                  },
                  "coid": {
                    "type": "string",
                    "description": "Client order ID",
                    "minLength": 32,
                    "maxLength": 32,
                    "pattern": "^[0-9a-f]{32}$",
                    "example": "550e8400e29b41d4a716446655440000"
                  },
                  "builder": {
                    "type": "object",
                    "description": "Saved builder terms. Address is the registered Perps account, and fee_rate is an additional fraction of executed notional. Terms survive approval revocation for existing orders.",
                    "required": ["address", "fee_rate"],
                    "properties": {
                      "address": {
                        "type": "string",
                        "description": "Address",
                        "example": "0x1234567890abcdef1234567890abcdef12345678"
                      },
                      "fee_rate": {
                        "type": "string",
                        "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                        "example": "0.001"
                      }
                    }
                  }
                },
                "required": [
                  "oid",
                  "iid",
                  "buy",
                  "p",
                  "qty",
                  "tif",
                  "po",
                  "ro",
                  "status",
                  "rest",
                  "fill",
                  "cts",
                  "uts"
                ]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "orders",
                "ts": 1767225600000,
                "ets": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "oid": 1234567890,
                  "iid": 1,
                  "buy": true,
                  "p": "100.00",
                  "qty": "10.00",
                  "tif": "gtc",
                  "po": false,
                  "ro": false,
                  "rest": "9.00",
                  "fill": "1.00",
                  "cts": 1767225600000,
                  "uts": 1767225600000,
                  "status": "open",
                  "coid": "550e8400e29b41d4a716446655440000",
                  "builder": {
                    "address": "0x1234567890abcdef1234567890abcdef12345678",
                    "fee_rate": "0.001"
                  }
                }
              }
            }
          ]
        }
      }
    },
    "funding": {
      "address": "/v1/ws",
      "title": "Funding",
      "summary": "Real-time funding payment updates. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "FundingSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private funding payment updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Funding private channel: \"funding\"",
                "items": {
                  "type": "string",
                  "enum": ["funding"]
                },
                "example": ["funding"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["funding"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "FundingSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to funding subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "FundingUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private funding updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Funding private channel: \"funding\"",
                "items": {
                  "type": "string",
                  "enum": ["funding"]
                },
                "example": ["funding"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["funding"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "FundingUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to funding unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "FundingUpdate",
          "title": "Update",
          "summary": "Real-time funding payment updates for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "Funding Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Funding payment object (one update per charged instrument)",
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "Funding payment ID. Probabilistically unique (same guarantees as trade IDs) and stable across REST and WebSocket for the same funding record.",
                    "example": 3055723280187747
                  },
                  "iid": {
                    "type": "integer",
                    "description": "Instrument ID",
                    "example": 1
                  },
                  "sz": {
                    "type": "string",
                    "description": "Signed position size in no. of contracts (positive = long, negative = short)",
                    "example": "10.00"
                  },
                  "fr": {
                    "type": "string",
                    "description": "Funding rate",
                    "example": "0.0001"
                  },
                  "fund": {
                    "type": "string",
                    "description": "Funding paid in USD",
                    "example": "1.00"
                  },
                  "fua": {
                    "type": "string",
                    "description": "Funding asset name",
                    "example": "USDC"
                  },
                  "ts": {
                    "type": "integer",
                    "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                    "example": 1767225600000
                  }
                },
                "required": ["id", "iid", "sz", "fr", "fund", "fua", "ts"]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "funding",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "id": 3055723280187747,
                  "iid": 1,
                  "sz": "10.00",
                  "fr": "0.0001",
                  "fund": "1.00",
                  "fua": "USDC",
                  "ts": 1767225600000
                }
              }
            }
          ]
        }
      }
    },
    "balances": {
      "address": "/v1/ws",
      "title": "Balances",
      "summary": "Real-time balance updates. Pushed every 5 seconds. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "BalancesSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private balance updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Balances private channel: \"balances\"",
                "items": {
                  "type": "string",
                  "enum": ["balances"]
                },
                "example": ["balances"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["balances"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "BalancesSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to balances subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "BalancesUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private balance updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Balances private channel: \"balances\"",
                "items": {
                  "type": "string",
                  "enum": ["balances"]
                },
                "example": ["balances"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["balances"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "BalancesUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to balances unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "BalancesUpdate",
          "title": "Update",
          "summary": "Balance updates pushed every 5 seconds",
          "contentType": "application/json",
          "payload": {
            "title": "Balances Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Balance object",
                "properties": {
                  "asset": {
                    "type": "string",
                    "description": "Asset name",
                    "example": "USDC"
                  },
                  "balance": {
                    "type": "string",
                    "description": "Total balance",
                    "example": "10000.00"
                  },
                  "value": {
                    "type": "string",
                    "description": "USD value",
                    "example": "10000.00"
                  }
                },
                "required": ["asset", "balance", "value"]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "balances",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "asset": "USDC",
                  "balance": "10000.00",
                  "value": "10000.00"
                }
              }
            }
          ]
        }
      }
    },
    "portfolio": {
      "address": "/v1/ws",
      "title": "Portfolio",
      "summary": "Real-time portfolio updates. Pushed every 5 seconds. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "PortfolioSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private portfolio updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Portfolio private channel: \"portfolio\"",
                "items": {
                  "type": "string",
                  "enum": ["portfolio"]
                },
                "example": ["portfolio"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["portfolio"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "PortfolioSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to portfolio subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "PortfolioUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private portfolio updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Portfolio private channel: \"portfolio\"",
                "items": {
                  "type": "string",
                  "enum": ["portfolio"]
                },
                "example": ["portfolio"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["portfolio"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "PortfolioUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to portfolio unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "PortfolioUpdate",
          "title": "Update",
          "summary": "Portfolio updates pushed every 5 seconds",
          "contentType": "application/json",
          "payload": {
            "title": "Portfolio Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "required": [
                  "positions",
                  "margin",
                  "withdrawable",
                  "in_liquidation",
                  "fee_tier",
                  "timestamp"
                ],
                "properties": {
                  "positions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "instrument_id",
                        "symbol",
                        "size",
                        "entry_price",
                        "leverage",
                        "cross",
                        "initial_margin",
                        "maintenance_margin",
                        "position_value",
                        "liquidation_price",
                        "unrealized_pnl",
                        "return_on_equity",
                        "cumulative_funding",
                        "adl_index"
                      ],
                      "properties": {
                        "instrument_id": {
                          "type": "integer",
                          "description": "Instrument ID"
                        },
                        "symbol": {
                          "type": "string",
                          "description": "Instrument symbol",
                          "example": "NVDA-USDC"
                        },
                        "size": {
                          "type": "string",
                          "description": "Signed position size in no. of contracts (positive = long, negative = short)",
                          "example": "10.00"
                        },
                        "entry_price": {
                          "type": "string",
                          "description": "Average entry price",
                          "example": "2986.30"
                        },
                        "leverage": {
                          "type": "integer",
                          "description": "Leverage",
                          "example": 10
                        },
                        "cross": {
                          "type": "boolean",
                          "description": "Whether to use cross margin mode"
                        },
                        "initial_margin": {
                          "type": "string",
                          "description": "Current collateral backing the position. For cross positions, this is\nthe required initial margin based on position size, mark price, the\napplicable risk tier, and configured leverage. For isolated positions,\nthis is the position's current equity: signed allocated margin plus\nunrealized PnL minus settled funding.\n\nThe legacy `initial_margin` name is retained for API compatibility;\n`margin` would more accurately describe the field.\n",
                          "example": "10.00"
                        },
                        "maintenance_margin": {
                          "type": "string",
                          "description": "Maintenance margin amount",
                          "example": "100.00"
                        },
                        "position_value": {
                          "type": "string",
                          "description": "Notional position value in USD",
                          "example": "100.03"
                        },
                        "liquidation_price": {
                          "type": "string",
                          "description": "Liquidation price",
                          "example": "2866.27"
                        },
                        "unrealized_pnl": {
                          "type": "string",
                          "description": "Unrealized PnL in USD",
                          "example": "-0.01"
                        },
                        "return_on_equity": {
                          "type": "string",
                          "description": "Unrealized PnL divided by the position's current required initial margin, as a decimal.",
                          "example": "-0.0027"
                        },
                        "cumulative_funding": {
                          "type": "string",
                          "description": "Cumulative funding paid/received in USD",
                          "example": "514.09"
                        },
                        "adl_index": {
                          "type": "integer",
                          "enum": [0, 1, 2, 3],
                          "description": "Auto-deleveraging tier; higher means higher risk of being ADL'd.",
                          "example": 2
                        }
                      }
                    }
                  },
                  "margin": {
                    "type": "object",
                    "required": [
                      "total_account_value",
                      "available_order_margin",
                      "total_initial_margin",
                      "total_maintenance_margin",
                      "total_position_value"
                    ],
                    "properties": {
                      "total_account_value": {
                        "type": "string",
                        "description": "Total account value in USD (equity + unrealized PnL)",
                        "example": "13109.48"
                      },
                      "available_order_margin": {
                        "type": "string",
                        "description": "Collateral available in USD for additional order initial margin after existing exposure, open orders, orders and isolated-margin additions awaiting risk processing, and pending withdrawals or transfers",
                        "example": "5055.79"
                      },
                      "total_initial_margin": {
                        "type": "string",
                        "description": "Total initial margin in use across all positions",
                        "example": "4.97"
                      },
                      "total_maintenance_margin": {
                        "type": "string",
                        "description": "Total maintenance margin across all positions",
                        "example": "2.49"
                      },
                      "total_position_value": {
                        "type": "string",
                        "description": "Total notional position value in USD",
                        "example": "100.03"
                      }
                    }
                  },
                  "withdrawable": {
                    "type": "string",
                    "description": "Withdrawable balance in USD",
                    "example": "13104.51"
                  },
                  "in_liquidation": {
                    "type": "boolean",
                    "description": "Whether the account is currently under liquidation"
                  },
                  "fee_tier": {
                    "type": "integer",
                    "description": "Zero-based index into `tiers` of the single perpetual fee schedule returned by `/v1/info/fees`, which applies to every perpetual regardless of category. Builder fees are additional and are not part of this tier. Defaults to 0 without a current tier assignment and is capped at the highest configured tier. WebSocket tier changes appear on the next portfolio update, published every 5 seconds.",
                    "example": 0
                  },
                  "timestamp": {
                    "type": "integer",
                    "description": "Update timestamp in milliseconds",
                    "example": 1767225600000
                  }
                }
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "portfolio",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "positions": [
                    {
                      "symbol": "NVDA-USDC",
                      "size": "10.00",
                      "entry_price": "2986.30",
                      "leverage": 10,
                      "initial_margin": "10.00",
                      "maintenance_margin": "100.00",
                      "position_value": "100.03",
                      "liquidation_price": "2866.27",
                      "unrealized_pnl": "-0.01",
                      "return_on_equity": "-0.0027",
                      "cumulative_funding": "514.09",
                      "adl_index": 2
                    }
                  ],
                  "margin": {
                    "total_account_value": "13109.48",
                    "available_order_margin": "13104.51",
                    "total_initial_margin": "4.97",
                    "total_maintenance_margin": "2.49",
                    "total_position_value": "100.03"
                  },
                  "withdrawable": "13104.51",
                  "timestamp": 1767225600000,
                  "fee_tier": 0
                }
              }
            }
          ]
        }
      }
    },
    "deposits": {
      "address": "/v1/ws",
      "title": "Deposits",
      "summary": "Real-time deposit status updates. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "DepositsSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private deposit updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Deposits private channel: \"deposits\"",
                "items": {
                  "type": "string",
                  "enum": ["deposits"]
                },
                "example": ["deposits"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["deposits"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "DepositsSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to deposits subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "DepositsUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private deposit updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Deposits private channel: \"deposits\"",
                "items": {
                  "type": "string",
                  "enum": ["deposits"]
                },
                "example": ["deposits"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["deposits"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "DepositsUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to deposits unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "DepositsUpdate",
          "title": "Update",
          "summary": "Deposit status updates for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "Deposits Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Array of deposit objects",
                "properties": {
                  "hash": {
                    "type": "string",
                    "description": "On-chain transaction hash, \"0x\" if not yet mined",
                    "default": "0x",
                    "example": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
                  },
                  "asset": {
                    "type": "string",
                    "description": "Asset name",
                    "example": "USDC"
                  },
                  "amount": {
                    "type": "string",
                    "description": "Token amount in decimal units (e.g. \"100\" for 100 USDC).",
                    "example": "100"
                  },
                  "status": {
                    "type": "string",
                    "description": "Deposit status",
                    "enum": ["pending", "confirmed", "removed"]
                  }
                },
                "required": ["hash", "asset", "amount", "status"]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "deposits",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
                    "asset": "USDC",
                    "amount": "100000000",
                    "status": "pending"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "withdrawals": {
      "address": "/v1/ws",
      "title": "Withdrawals",
      "summary": "Real-time withdrawal status updates. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "WithdrawalsSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private withdrawal updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Withdrawals private channel: \"withdrawals\"",
                "items": {
                  "type": "string",
                  "enum": ["withdrawals"]
                },
                "example": ["withdrawals"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["withdrawals"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "WithdrawalsSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to withdrawals subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "WithdrawalsUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private withdrawal updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Withdrawals private channel: \"withdrawals\"",
                "items": {
                  "type": "string",
                  "enum": ["withdrawals"]
                },
                "example": ["withdrawals"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["withdrawals"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "WithdrawalsUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to withdrawals unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "WithdrawalsUpdate",
          "title": "Update",
          "summary": "Withdrawal status updates for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "Withdrawals Update",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "description": "Array of withdrawal objects",
                "properties": {
                  "withdraw_id": {
                    "type": "integer",
                    "description": "Withdraw ID"
                  },
                  "asset": {
                    "type": "string",
                    "description": "Asset name",
                    "example": "USDC"
                  },
                  "amount": {
                    "type": "string",
                    "description": "Token amount in decimal units (e.g. \"100\" for 100 USDC).",
                    "example": "100"
                  },
                  "fee": {
                    "type": "string",
                    "description": "Withdrawal transaction fee in decimalized asset units",
                    "example": "5.00"
                  },
                  "to": {
                    "type": "string",
                    "description": "Destination address in hex format",
                    "example": "0x1234567890abcdef1234567890abcdef12345678"
                  },
                  "status": {
                    "type": "string",
                    "description": "Withdrawal status",
                    "enum": ["pending", "confirmed", "removed", "failed"]
                  },
                  "hash": {
                    "type": "string",
                    "description": "On-chain transaction hash, \"0x\" if not yet mined",
                    "default": "0x",
                    "example": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
                  }
                },
                "required": [
                  "withdraw_id",
                  "asset",
                  "amount",
                  "fee",
                  "to",
                  "status",
                  "hash"
                ]
              }
            },
            "required": ["ch", "ts", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "withdrawals",
                "ts": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "asset": "USDC",
                    "amount": "100000000",
                    "fee": "5.00",
                    "to": "0x1234567890abcdef1234567890abcdef12345678",
                    "status": "pending",
                    "hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "notifications": {
      "address": "/v1/ws",
      "title": "Notifications",
      "summary": "Real-time perps notifications for the in-app bell. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "NotificationsSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private perps notifications (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Notifications private channel: \"notifications\"",
                "items": {
                  "type": "string",
                  "enum": ["notifications"]
                },
                "example": ["notifications"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["notifications"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "NotificationsSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to notifications subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "NotificationsUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private perps notifications",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "Notifications private channel: \"notifications\"",
                "items": {
                  "type": "string",
                  "enum": ["notifications"]
                },
                "example": ["notifications"]
              }
            },
            "required": ["req", "chs"]
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["notifications"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "NotificationsUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to notifications unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "NotificationsUpdate",
          "title": "Update",
          "summary": "Real-time perps notification frame (data or resync) for authenticated users",
          "contentType": "application/json",
          "payload": {
            "oneOf": [
              {
                "type": "object",
                "title": "Base Update",
                "properties": {
                  "ch": {
                    "const": "notifications"
                  },
                  "ts": {
                    "type": "integer",
                    "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                    "example": 1767225600000
                  },
                  "sq": {
                    "type": "integer",
                    "description": "Sequence number",
                    "example": 1234567890
                  },
                  "data": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                            "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "position_opened",
                              "position_increased",
                              "position_reduced"
                            ]
                          },
                          "instrument_id": {
                            "type": "integer",
                            "description": "Instrument ID"
                          },
                          "side": {
                            "type": "string",
                            "description": "Side",
                            "enum": ["long", "short"]
                          },
                          "size": {
                            "type": "string",
                            "description": "Quantity in no. of contracts",
                            "example": "10.00"
                          },
                          "avg_price": {
                            "type": "string",
                            "description": "Volume-weighted average fill price in USD",
                            "example": "64210"
                          },
                          "leverage": {
                            "type": "integer",
                            "description": "Leverage",
                            "example": 10
                          },
                          "order_type": {
                            "type": "string",
                            "description": "Kind of order whose execution produced this notification, decided by the account's own order in the fill. A TP/SL-triggered order reports the trigger that fired it (take_profit / stop_loss) whether it aggressed or rested; otherwise an aggressor submitted without a limit price is market and everything else — including a maker's resting order — is limit. Optional — omitted when the deriver cannot attribute the fill to an order (e.g. a consumer restarted inside the trigger-to-fill window).",
                            "enum": [
                              "market",
                              "limit",
                              "take_profit",
                              "stop_loss"
                            ]
                          },
                          "fill_qty": {
                            "type": "string",
                            "description": "Quantity filled in this event, in no. of contracts. When the account has more than one fill in the event, this is their combined quantity. Always a positive decimal string.",
                            "example": "0.05"
                          },
                          "order_qty": {
                            "type": "string",
                            "description": "Original total quantity of the account's own order that produced the fill, in no. of contracts. Optional: omitted when the deriver cannot resolve the order, or when the account's fills in this event span multiple of its own orders (fill_qty then combines quantities across orders, so no single original quantity applies). order_qty can be present while order_type is absent, because order_type is also omitted when a triggered order's conditional cannot be classified.",
                            "example": "0.10"
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "instrument_id",
                          "side",
                          "size",
                          "avg_price",
                          "leverage",
                          "fill_qty"
                        ]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                            "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                          },
                          "type": {
                            "type": "string",
                            "const": "position_closed"
                          },
                          "instrument_id": {
                            "type": "integer",
                            "description": "Instrument ID"
                          },
                          "side": {
                            "type": "string",
                            "description": "Side",
                            "enum": ["long", "short"]
                          },
                          "size": {
                            "type": "string",
                            "description": "Quantity in no. of contracts",
                            "example": "10.00"
                          },
                          "avg_price": {
                            "type": "string",
                            "description": "Volume-weighted average fill price in USD",
                            "example": "64210"
                          },
                          "pnl": {
                            "type": "string",
                            "description": "PnL in USD",
                            "example": "100.00"
                          },
                          "order_type": {
                            "type": "string",
                            "description": "Kind of order whose execution produced this notification, decided by the account's own order in the fill. A TP/SL-triggered order reports the trigger that fired it (take_profit / stop_loss) whether it aggressed or rested; otherwise an aggressor submitted without a limit price is market and everything else — including a maker's resting order — is limit. Optional — omitted when the deriver cannot attribute the fill to an order (e.g. a consumer restarted inside the trigger-to-fill window).",
                            "enum": [
                              "market",
                              "limit",
                              "take_profit",
                              "stop_loss"
                            ]
                          },
                          "fill_qty": {
                            "type": "string",
                            "description": "Quantity filled in this event, in no. of contracts. When the account has more than one fill in the event, this is their combined quantity. Always a positive decimal string.",
                            "example": "0.05"
                          },
                          "order_qty": {
                            "type": "string",
                            "description": "Original total quantity of the account's own order that produced the fill, in no. of contracts. Optional: omitted when the deriver cannot resolve the order, or when the account's fills in this event span multiple of its own orders (fill_qty then combines quantities across orders, so no single original quantity applies). order_qty can be present while order_type is absent, because order_type is also omitted when a triggered order's conditional cannot be classified.",
                            "example": "0.10"
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "instrument_id",
                          "side",
                          "size",
                          "avg_price",
                          "pnl",
                          "fill_qty"
                        ]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                            "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                          },
                          "type": {
                            "type": "string",
                            "const": "limit_order_canceled"
                          },
                          "instrument_id": {
                            "type": "integer",
                            "description": "Instrument ID"
                          },
                          "side": {
                            "type": "string",
                            "description": "Side",
                            "enum": ["long", "short"]
                          },
                          "size": {
                            "type": "string",
                            "description": "Quantity in no. of contracts",
                            "example": "10.00"
                          },
                          "price": {
                            "type": "string",
                            "description": "Price",
                            "example": "100.00"
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "instrument_id",
                          "side",
                          "size",
                          "price"
                        ]
                      },
                      {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                                "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                              },
                              "type": {
                                "type": "string",
                                "const": "liquidation_warning"
                              },
                              "instrument_id": {
                                "type": "integer",
                                "description": "Instrument ID"
                              },
                              "margin_type": {
                                "type": "string",
                                "const": "isolated"
                              },
                              "mark_price": {
                                "type": "string",
                                "description": "Mark price",
                                "example": "100.00"
                              },
                              "liq_price": {
                                "type": "string",
                                "description": "Liquidation price",
                                "example": "2866.27"
                              }
                            },
                            "required": [
                              "id",
                              "type",
                              "instrument_id",
                              "margin_type",
                              "mark_price",
                              "liq_price"
                            ],
                            "not": {
                              "required": ["affected_instruments"]
                            }
                          },
                          {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                                "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                              },
                              "type": {
                                "type": "string",
                                "const": "liquidation_warning"
                              },
                              "instrument_id": {
                                "type": "null"
                              },
                              "margin_type": {
                                "type": "string",
                                "const": "cross"
                              },
                              "mark_price": {
                                "type": "string",
                                "description": "Mark price",
                                "example": "100.00"
                              },
                              "affected_instruments": {
                                "type": "array",
                                "description": "Instrument ids contributing to a cross-margin liquidation warning",
                                "items": {
                                  "type": "integer"
                                },
                                "example": [42, 7]
                              }
                            },
                            "required": [
                              "id",
                              "type",
                              "instrument_id",
                              "margin_type",
                              "mark_price",
                              "affected_instruments"
                            ],
                            "not": {
                              "required": ["liq_price"]
                            }
                          }
                        ]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                            "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                          },
                          "type": {
                            "type": "string",
                            "const": "position_liquidated"
                          },
                          "instrument_id": {
                            "type": "integer",
                            "description": "Instrument ID"
                          },
                          "side": {
                            "type": "string",
                            "description": "Side",
                            "enum": ["long", "short"]
                          },
                          "size_closed": {
                            "type": "string",
                            "description": "Position size closed by a liquidation (base units)",
                            "example": "0.05"
                          },
                          "pnl": {
                            "type": ["string", "null"],
                            "description": "Realized PnL in USD; null when not available (e.g. a backstop close with no fill)",
                            "example": "290.00"
                          },
                          "margin_type": {
                            "type": "string",
                            "description": "Margin mode",
                            "enum": ["cross", "isolated"]
                          },
                          "via_backstop": {
                            "type": "boolean",
                            "description": "Whether an insurance-fund backstop applied to the liquidation",
                            "example": false
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "instrument_id",
                          "side",
                          "size_closed",
                          "pnl",
                          "margin_type",
                          "via_backstop"
                        ]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable notification id. The same notification always has the same id on the WebSocket feed and in the notifications history, so you can safely deduplicate across the two.",
                            "example": "0a5d8f1e-3b2c-5e4a-9f8b-1c2d3e4f5a6b"
                          },
                          "type": {
                            "type": "string",
                            "const": "position_deleveraged"
                          },
                          "instrument_id": {
                            "type": "integer",
                            "description": "Instrument ID"
                          },
                          "side": {
                            "type": "string",
                            "description": "Side",
                            "enum": ["long", "short"]
                          },
                          "size_closed": {
                            "type": "string",
                            "description": "Position size closed by auto-deleveraging (base units)",
                            "example": "0.05"
                          },
                          "price": {
                            "type": "string",
                            "description": "Price",
                            "example": "100.00"
                          },
                          "pnl": {
                            "type": "string",
                            "description": "PnL in USD",
                            "example": "100.00"
                          },
                          "margin_type": {
                            "type": "string",
                            "description": "Margin mode",
                            "enum": ["cross", "isolated"]
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "instrument_id",
                          "side",
                          "size_closed",
                          "price",
                          "pnl",
                          "margin_type"
                        ]
                      }
                    ]
                  }
                },
                "required": ["ch", "ts", "sq", "data"]
              },
              {
                "description": "Resync control frame sent when the connection falls behind and the server drops one or more data frames. Its sq is the highest sequence among the dropped notifications. To recover, backfill from the REST notifications history anchored at the last data frame you processed, and keep paging until the returned durable_source_seq reaches this sq and no more pages remain.",
                "type": "object",
                "title": "Base Update",
                "properties": {
                  "ch": {
                    "const": "notifications"
                  },
                  "ts": {
                    "type": "integer",
                    "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                    "example": 1767225600000
                  },
                  "sq": {
                    "type": "integer",
                    "description": "Sequence number",
                    "example": 1234567890
                  },
                  "type": {
                    "const": "resync"
                  }
                },
                "required": ["ch", "ts", "sq", "type"],
                "not": {
                  "required": ["data"]
                }
              }
            ]
          }
        }
      }
    },
    "modifyOrders": {
      "address": "/v1/ws",
      "title": "Modify Orders",
      "summary": "Modify existing orders by exchange order ID.",
      "description": "Modify existing orders by exchange order ID. Only price and total quantity\nare mutable.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **1 / order**</Badge>\n",
      "messages": {
        "Request": {
          "name": "ModifyOrdersRequest",
          "title": "Modify Orders Request",
          "summary": "Client submits a signed order modification request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["modifyOrders"]
                  },
                  "args": {
                    "type": "array",
                    "minItems": 1,
                    "description": "Array of orders to modify",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": ["oid", "p", "qty"],
                      "properties": {
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "p": {
                          "type": "string",
                          "description": "Price",
                          "example": "100.00"
                        },
                        "qty": {
                          "type": "string",
                          "description": "Quantity in no. of contracts",
                          "example": "10.00"
                        }
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "exp": {
                "type": "integer",
                "description": "Command-processing deadline in Unix milliseconds, not an order auto-cancel time; the server caps it at now + 5 s, clamps larger values to that cap, and uses that 5 s default when omitted. Values at or before the server's clock are rejected with HTTP 400 (command expired).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Modify by order ID",
              "payload": {
                "id": 2,
                "req": "post",
                "op": {
                  "type": "modifyOrders",
                  "args": [
                    {
                      "oid": 1234567890,
                      "p": "100.25",
                      "qty": "8"
                    }
                  ]
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000,
                "exp": 1767225660000
              }
            }
          ]
        },
        "Response": {
          "name": "ModifyOrdersResponse",
          "title": "Modify Orders Response",
          "summary": "Server responds with modify result for each order",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "array",
                "description": "Array of modify results. A request-level failure is returned as\na single rejected item.\n",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status", "order"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        },
                        "order": {
                          "type": "object",
                          "required": [
                            "oid",
                            "iid",
                            "buy",
                            "p",
                            "qty",
                            "tif",
                            "po",
                            "ro",
                            "status",
                            "rest",
                            "fill",
                            "cts",
                            "uts"
                          ],
                          "properties": {
                            "oid": {
                              "type": "integer",
                              "description": "Order ID",
                              "example": 1234567890
                            },
                            "iid": {
                              "type": "integer",
                              "description": "Instrument ID",
                              "example": 1
                            },
                            "buy": {
                              "type": "boolean",
                              "description": "Is buy",
                              "example": true
                            },
                            "p": {
                              "type": "string",
                              "description": "Price",
                              "example": "100.00"
                            },
                            "qty": {
                              "type": "string",
                              "description": "Quantity in no. of contracts",
                              "example": "10.00"
                            },
                            "tif": {
                              "type": "string",
                              "description": "Time in force",
                              "enum": ["gtc", "ioc", "fok"]
                            },
                            "po": {
                              "type": "boolean",
                              "description": "Post only",
                              "default": false,
                              "example": false
                            },
                            "ro": {
                              "type": "boolean",
                              "description": "Reduce only",
                              "example": false,
                              "default": false
                            },
                            "rest": {
                              "type": "string",
                              "description": "Resting quantity",
                              "example": "9.00"
                            },
                            "fill": {
                              "type": "string",
                              "description": "Filled quantity",
                              "example": "1.00"
                            },
                            "cts": {
                              "type": "integer",
                              "description": "Create timestamp in milliseconds",
                              "example": 1767225600000
                            },
                            "uts": {
                              "type": "integer",
                              "description": "Update timestamp in milliseconds",
                              "example": 1767225600000
                            },
                            "status": {
                              "type": "string",
                              "description": "Order status",
                              "example": "open"
                            },
                            "coid": {
                              "type": "string",
                              "description": "Client order ID",
                              "minLength": 32,
                              "maxLength": 32,
                              "pattern": "^[0-9a-f]{32}$",
                              "example": "550e8400e29b41d4a716446655440000"
                            },
                            "builder": {
                              "type": "object",
                              "description": "Saved builder terms. Address is the registered Perps account, and fee_rate is an additional fraction of executed notional. Terms survive approval revocation for existing orders.",
                              "required": ["address", "fee_rate"],
                              "properties": {
                                "address": {
                                  "type": "string",
                                  "description": "Address",
                                  "example": "0x1234567890abcdef1234567890abcdef12345678"
                                },
                                "fee_rate": {
                                  "type": "string",
                                  "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                                  "example": "0.001"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "description": "Server rejection timestamp in Unix milliseconds.",
                          "type": "integer",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Order modified",
              "payload": {
                "id": 2,
                "data": [
                  {
                    "status": "ok",
                    "order": {
                      "oid": 1234567890,
                      "iid": 1,
                      "buy": true,
                      "p": "100.25",
                      "qty": "8",
                      "tif": "gtc",
                      "po": false,
                      "ro": false,
                      "rest": "8",
                      "fill": "0",
                      "status": "open",
                      "cts": 1767225600000,
                      "uts": 1767225601000
                    }
                  }
                ]
              }
            },
            {
              "name": "Request rejected",
              "payload": {
                "id": 2,
                "data": [
                  {
                    "status": "err",
                    "error": "message_rate_limited"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "modifyOrdersCOID": {
      "address": "/v1/ws",
      "title": "Modify Orders COID",
      "summary": "Modify existing orders by client order ID.",
      "description": "Modify existing orders by client order ID. Only price and total quantity are\nmutable.\nRequires proxy signature, see [proxy signing](/http/signing#2-proxy-signing).\n\n<Badge color=\"gray\" size=\"md\">Action Weight: **1 / order**</Badge>\n",
      "messages": {
        "Request": {
          "name": "ModifyOrdersCoidRequest",
          "title": "Modify Orders COID Request",
          "summary": "Client submits signed order modifications by client order ID",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "op": {
                "type": "object",
                "required": ["type", "args"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["modifyOrdersCOID"]
                  },
                  "args": {
                    "type": "array",
                    "minItems": 1,
                    "description": "Array of orders to modify by client order ID",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": ["coid", "p", "qty"],
                      "properties": {
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "p": {
                          "type": "string",
                          "description": "Price",
                          "example": "100.00"
                        },
                        "qty": {
                          "type": "string",
                          "description": "Quantity in no. of contracts",
                          "example": "10.00"
                        }
                      }
                    }
                  }
                }
              },
              "sig": {
                "type": "string",
                "description": "Signature in hex format",
                "example": "0x1234567890..."
              },
              "salt": {
                "type": "integer",
                "description": "Salt",
                "example": 1234567890
              },
              "ts": {
                "type": "integer",
                "description": "Request timestamp. Unix milliseconds for most operations; Unix seconds for withdrawals (must match the on-chain EIP-712 struct verified against block.timestamp).",
                "example": 1767225600000
              },
              "exp": {
                "type": "integer",
                "description": "Command-processing deadline in Unix milliseconds, not an order auto-cancel time; the server caps it at now + 5 s, clamps larger values to that cap, and uses that 5 s default when omitted. Values at or before the server's clock are rejected with HTTP 400 (command expired).",
                "example": 1767225600000
              }
            },
            "required": ["req", "op", "sig", "salt", "ts"]
          },
          "examples": [
            {
              "name": "Modify by client order ID",
              "payload": {
                "id": 2,
                "req": "post",
                "op": {
                  "type": "modifyOrdersCOID",
                  "args": [
                    {
                      "coid": "550e8400e29b41d4a716446655440000",
                      "p": "100.25",
                      "qty": "8"
                    }
                  ]
                },
                "sig": "0x1234567890...",
                "salt": 1234567890,
                "ts": 1767225600000,
                "exp": 1767225660000
              }
            }
          ]
        },
        "Response": {
          "name": "ModifyOrdersCoidResponse",
          "title": "Modify Orders COID Response",
          "summary": "Server responds with modify result for each client order ID",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "type": "array",
                "description": "Array of modify results",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status", "order"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        },
                        "order": {
                          "type": "object",
                          "required": [
                            "oid",
                            "iid",
                            "buy",
                            "p",
                            "qty",
                            "tif",
                            "po",
                            "ro",
                            "status",
                            "rest",
                            "fill",
                            "cts",
                            "uts"
                          ],
                          "properties": {
                            "oid": {
                              "type": "integer",
                              "description": "Order ID",
                              "example": 1234567890
                            },
                            "iid": {
                              "type": "integer",
                              "description": "Instrument ID",
                              "example": 1
                            },
                            "buy": {
                              "type": "boolean",
                              "description": "Is buy",
                              "example": true
                            },
                            "p": {
                              "type": "string",
                              "description": "Price",
                              "example": "100.00"
                            },
                            "qty": {
                              "type": "string",
                              "description": "Quantity in no. of contracts",
                              "example": "10.00"
                            },
                            "tif": {
                              "type": "string",
                              "description": "Time in force",
                              "enum": ["gtc", "ioc", "fok"]
                            },
                            "po": {
                              "type": "boolean",
                              "description": "Post only",
                              "default": false,
                              "example": false
                            },
                            "ro": {
                              "type": "boolean",
                              "description": "Reduce only",
                              "example": false,
                              "default": false
                            },
                            "rest": {
                              "type": "string",
                              "description": "Resting quantity",
                              "example": "9.00"
                            },
                            "fill": {
                              "type": "string",
                              "description": "Filled quantity",
                              "example": "1.00"
                            },
                            "cts": {
                              "type": "integer",
                              "description": "Create timestamp in milliseconds",
                              "example": 1767225600000
                            },
                            "uts": {
                              "type": "integer",
                              "description": "Update timestamp in milliseconds",
                              "example": 1767225600000
                            },
                            "status": {
                              "type": "string",
                              "description": "Order status",
                              "example": "open"
                            },
                            "coid": {
                              "type": "string",
                              "description": "Client order ID",
                              "minLength": 32,
                              "maxLength": 32,
                              "pattern": "^[0-9a-f]{32}$",
                              "example": "550e8400e29b41d4a716446655440000"
                            },
                            "builder": {
                              "type": "object",
                              "description": "Saved builder terms. Address is the registered Perps account, and fee_rate is an additional fraction of executed notional. Terms survive approval revocation for existing orders.",
                              "required": ["address", "fee_rate"],
                              "properties": {
                                "address": {
                                  "type": "string",
                                  "description": "Address",
                                  "example": "0x1234567890abcdef1234567890abcdef12345678"
                                },
                                "fee_rate": {
                                  "type": "string",
                                  "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                                  "example": "0.001"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "oid": {
                          "type": "integer",
                          "description": "Order ID",
                          "example": 1234567890
                        },
                        "coid": {
                          "type": "string",
                          "description": "Client order ID",
                          "minLength": 32,
                          "maxLength": 32,
                          "pattern": "^[0-9a-f]{32}$",
                          "example": "550e8400e29b41d4a716446655440000"
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "description": "Server rejection timestamp in Unix milliseconds.",
                          "type": "integer",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "Order modified",
              "payload": {
                "id": 2,
                "data": [
                  {
                    "status": "ok",
                    "order": {
                      "oid": 1234567890,
                      "coid": "550e8400e29b41d4a716446655440000",
                      "iid": 1,
                      "buy": true,
                      "p": "100.25",
                      "qty": "8",
                      "tif": "gtc",
                      "po": false,
                      "ro": false,
                      "rest": "8",
                      "fill": "0",
                      "status": "open",
                      "cts": 1767225600000,
                      "uts": 1767225601000
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "builderFills": {
      "address": "/v1/ws",
      "title": "BuilderFills",
      "summary": "Real-time attributed fills for the authenticated builder account. Requires prior authentication.",
      "messages": {
        "SubscribeRequest": {
          "name": "BuilderFillsSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to attributed fill updates for the authenticated builder (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "description": "Client-supplied identifier used to correlate the response.",
                "type": "integer"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "BuilderFills private channel: \"builderFills\"",
                "items": {
                  "type": "string",
                  "enum": ["builderFills"]
                },
                "example": ["builderFills"]
              }
            },
            "required": ["req", "chs"],
            "description": "Each inbound request consumes a weighted WebSocket message token. Before\nauthentication the budget is per client IP. After authentication all of\nthe account's sockets share its tier budget across IPs. The first valid\nsigned write also binds an unauthenticated socket to its recovered account.\nLater signed writes must resolve that same account. A breach returns\n`message_rate_limited` and leaves the socket open.\n\nSigned write posts carrying an `id` are dispatched concurrently (up to 16\nin flight per connection) and may execute and respond out of request\norder, matching the semantics of concurrent HTTP requests. Ordering is\nkept per connection for posts that name the same client order id or\norder id, and `cancelAll`, leverage and margin updates wait for every\nearlier post on the connection while later posts wait for them. Posts\nwithout an `id` are dispatched one at a time but are not ordered after\nearlier `id`-carrying posts still in flight. For strict ordering, await\neach response before sending the next request, or omit `id` on every\npost. Use a unique `id` for every in-flight request on a connection.\nUniqueness is not enforced and duplicate in-flight IDs are ambiguous.\n"
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["builderFills"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "BuilderFillsSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to fills subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `unauthorized`, `not_found`. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "type": "integer",
                          "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "BuilderFillsUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from attributed fill updates for the authenticated builder",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "description": "Client-supplied identifier used to correlate the response.",
                "type": "integer"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "BuilderFills private channel: \"builderFills\"",
                "items": {
                  "type": "string",
                  "enum": ["builderFills"]
                },
                "example": ["builderFills"]
              }
            },
            "required": ["req", "chs"],
            "description": "Each inbound request consumes a weighted WebSocket message token. Before\nauthentication the budget is per client IP. After authentication all of\nthe account's sockets share its tier budget across IPs. The first valid\nsigned write also binds an unauthenticated socket to its recovered account.\nLater signed writes must resolve that same account. A breach returns\n`message_rate_limited` and leaves the socket open.\n\nSigned write posts carrying an `id` are dispatched concurrently (up to 16\nin flight per connection) and may execute and respond out of request\norder, matching the semantics of concurrent HTTP requests. Ordering is\nkept per connection for posts that name the same client order id or\norder id, and `cancelAll`, leverage and margin updates wait for every\nearlier post on the connection while later posts wait for them. Posts\nwithout an `id` are dispatched one at a time but are not ordered after\nearlier `id`-carrying posts still in flight. For strict ordering, await\neach response before sending the next request, or omit `id` on every\npost. Use a unique `id` for every in-flight request on a connection.\nUniqueness is not enforced and duplicate in-flight IDs are ambiguous.\n"
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["builderFills"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "BuilderFillsUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to fills unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `unauthorized`, `not_found`. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "type": "integer",
                          "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "BuilderFillsUpdate",
          "title": "Update",
          "summary": "Real-time fill updates for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "Builder Fills Update",
            "description": "Attributed fill sides for the authenticated builder, including zero builder fees. Each receipt uses the same fields and earning_id as GET /v1/account/builder-earnings. The trader is the main account wallet, never a delegated trading key. There is no initial history snapshot and delivery is not exactly once. After reconnecting, subscribe first, buffer live receipts, then page REST history over an overlapping time window. History can lag the live feed. Use its complete as_of_sequence cutoff, repeat recovery until indexing catches up, and deduplicate by earning_id.",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Private channels use plain names (e.g. \"fills\", \"orders\").",
                "example": "builderFills"
              },
              "ts": {
                "description": "Server send time, Unix milliseconds",
                "type": "integer",
                "example": 1767225600000
              },
              "ets": {
                "type": "integer",
                "description": "Timestamp of the newest event this update reflects, in Unix milliseconds. Distinct from `ts`, which is the server send time. `ts - ets` is time spent inside the exchange after the event. `ets=0` means no event horizon is attested, and consumers must treat the horizon as unknown.",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "earning_id",
                    "trade_id",
                    "order_id",
                    "instrument_id",
                    "trader",
                    "buy",
                    "price",
                    "quantity",
                    "side",
                    "timestamp",
                    "sequence",
                    "notional",
                    "fee_asset",
                    "fee",
                    "builder_fee",
                    "total_fee",
                    "fee_rate"
                  ],
                  "properties": {
                    "earning_id": {
                      "type": "string",
                      "description": "Stable side-specific receipt identity, unique for this builder. Use this to deduplicate, not sequence or trade_id alone."
                    },
                    "trade_id": {
                      "type": "integer",
                      "description": "Trade ID",
                      "example": 1
                    },
                    "order_id": {
                      "type": "integer",
                      "description": "Order ID",
                      "example": 1234567890
                    },
                    "instrument_id": {
                      "type": "integer",
                      "description": "Instrument ID",
                      "example": 1
                    },
                    "trader": {
                      "description": "Main address of the attributed trading account, not its signing proxy or the counterparty.",
                      "type": "string",
                      "example": "0x1234567890abcdef1234567890abcdef12345678"
                    },
                    "buy": {
                      "type": "boolean",
                      "description": "Is buy",
                      "example": true
                    },
                    "price": {
                      "type": "string",
                      "description": "Price",
                      "example": "100.00"
                    },
                    "quantity": {
                      "type": "string",
                      "description": "Quantity in number of contracts",
                      "example": "10.00"
                    },
                    "client_order_id": {
                      "description": "Included only when the attributed order supplied a client_order_id.",
                      "type": "string",
                      "minLength": 32,
                      "maxLength": 32,
                      "pattern": "^[0-9a-f]{32}$",
                      "example": "550e8400e29b41d4a716446655440000"
                    },
                    "side": {
                      "type": "string",
                      "enum": ["maker", "taker"]
                    },
                    "timestamp": {
                      "type": "integer",
                      "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                      "example": 1767225600000
                    },
                    "sequence": {
                      "type": "integer"
                    },
                    "notional": {
                      "type": "string"
                    },
                    "fee_asset": {
                      "type": "string",
                      "description": "Fee asset name",
                      "example": "pUSD"
                    },
                    "fee": {
                      "type": "string",
                      "description": "Signed exchange fee for this trade side, excluding builder_fee. Negative values are rebates",
                      "example": "0.125"
                    },
                    "builder_fee": {
                      "type": "string",
                      "description": "Actual additional builder fee in the same asset as fee, floored independently for each execution to that asset's token decimals (six for pUSD), with discarded dust and no carry. The fee is non-negative and is zero for older or untagged fills and excluded forced liquidation legs.",
                      "example": "1.00"
                    },
                    "total_fee": {
                      "type": "string",
                      "description": "Exact signed sum of exchange fee and builder_fee in the same asset. May be negative when exchange rebates exceed the builder charge.",
                      "example": "1.125"
                    },
                    "fee_rate": {
                      "type": "string",
                      "description": "Additional builder fee as a decimal fraction of executed notional, from 0 through 0.001 (10 basis points). Zero approval revokes future admission. Never a percentage string.",
                      "example": "0.001"
                    }
                  }
                }
              }
            },
            "required": ["ch", "ts", "ets", "sq", "data"]
          },
          "examples": [
            {
              "name": "Update Example",
              "payload": {
                "ch": "builderFills",
                "ts": 1767225600000,
                "ets": 1767225600000,
                "sq": 1234567890,
                "data": [
                  {
                    "earning_id": "1:1:0",
                    "trade_id": 1,
                    "order_id": 1234567890,
                    "instrument_id": 1,
                    "trader": "0x1234567890abcdef1234567890abcdef12345678",
                    "buy": true,
                    "price": "100.00",
                    "quantity": "10.00",
                    "client_order_id": "550e8400e29b41d4a716446655440000",
                    "side": "maker",
                    "sequence": 1234567890,
                    "notional": "1000.00",
                    "timestamp": 1767225600000,
                    "fee_asset": "pUSD",
                    "fee": "0.125",
                    "builder_fee": "1.00",
                    "total_fee": "1.125",
                    "fee_rate": "0.001"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    "tpsl": {
      "address": "/v1/ws",
      "title": "TP/SL",
      "summary": "Real-time TP/SL lifecycle transitions. Requires authentication, see [Auth](/ws/auth).",
      "messages": {
        "SubscribeRequest": {
          "name": "TpslSubscribeRequest",
          "title": "Subscribe",
          "summary": "Subscribe to private TP/SL updates (requires prior auth)",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "description": "Client-supplied identifier used to correlate the response.",
                "type": "integer"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "TP/SL private channel: \"tpsl\"",
                "items": {
                  "type": "string",
                  "enum": ["tpsl"]
                },
                "example": ["tpsl"]
              }
            },
            "required": ["req", "chs"],
            "description": "Each inbound request consumes a weighted WebSocket message token. Before\nauthentication the budget is per client IP. After authentication all of\nthe account's sockets share its tier budget across IPs. The first valid\nsigned write also binds an unauthenticated socket to its recovered account.\nLater signed writes must resolve that same account. A breach returns\n`message_rate_limited` and leaves the socket open.\n\nSigned write posts carrying an `id` are dispatched concurrently (up to 16\nin flight per connection) and may execute and respond out of request\norder, matching the semantics of concurrent HTTP requests. Ordering is\nkept per connection for posts that name the same client order id or\norder id, and `cancelAll`, leverage and margin updates wait for every\nearlier post on the connection while later posts wait for them. Posts\nwithout an `id` are dispatched one at a time but are not ordered after\nearlier `id`-carrying posts still in flight. For strict ordering, await\neach response before sending the next request, or omit `id` on every\npost. Use a unique `id` for every in-flight request on a connection.\nUniqueness is not enforced and duplicate in-flight IDs are ambiguous.\n"
          },
          "examples": [
            {
              "name": "SubscribeRequest Example",
              "payload": {
                "req": "sub",
                "chs": ["tpsl"]
              }
            }
          ]
        },
        "SubscribeResponse": {
          "name": "TpslSubscribeResponse",
          "title": "Subscribe Response",
          "summary": "Response to TP/SL subscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `settlement_close_only_required`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "type": "integer",
                          "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "SubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "UnsubscribeRequest": {
          "name": "TpslUnsubscribeRequest",
          "title": "Unsubscribe",
          "summary": "Unsubscribe from private TP/SL updates",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Request",
            "properties": {
              "id": {
                "description": "Client-supplied identifier used to correlate the response.",
                "type": "integer"
              },
              "req": {
                "type": "string",
                "description": "Request type",
                "enum": ["post", "sub", "unsub"]
              },
              "chs": {
                "type": "array",
                "description": "TP/SL private channel: \"tpsl\"",
                "items": {
                  "type": "string",
                  "enum": ["tpsl"]
                },
                "example": ["tpsl"]
              }
            },
            "required": ["req", "chs"],
            "description": "Each inbound request consumes a weighted WebSocket message token. Before\nauthentication the budget is per client IP. After authentication all of\nthe account's sockets share its tier budget across IPs. The first valid\nsigned write also binds an unauthenticated socket to its recovered account.\nLater signed writes must resolve that same account. A breach returns\n`message_rate_limited` and leaves the socket open.\n\nSigned write posts carrying an `id` are dispatched concurrently (up to 16\nin flight per connection) and may execute and respond out of request\norder, matching the semantics of concurrent HTTP requests. Ordering is\nkept per connection for posts that name the same client order id or\norder id, and `cancelAll`, leverage and margin updates wait for every\nearlier post on the connection while later posts wait for them. Posts\nwithout an `id` are dispatched one at a time but are not ordered after\nearlier `id`-carrying posts still in flight. For strict ordering, await\neach response before sending the next request, or omit `id` on every\npost. Use a unique `id` for every in-flight request on a connection.\nUniqueness is not enforced and duplicate in-flight IDs are ambiguous.\n"
          },
          "examples": [
            {
              "name": "UnsubscribeRequest Example",
              "payload": {
                "req": "unsub",
                "chs": ["tpsl"]
              }
            }
          ]
        },
        "UnsubscribeResponse": {
          "name": "TpslUnsubscribeResponse",
          "title": "Unsubscribe Response",
          "summary": "Response to TP/SL unsubscribe request",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "title": "Base Response",
            "properties": {
              "id": {
                "type": "integer",
                "description": "Correlation ID for request-response matching"
              },
              "data": {
                "title": "Subscribe Response",
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["status"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["ok"]
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["status", "error"],
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": ["err"]
                        },
                        "error": {
                          "type": "string",
                          "description": "Error identifier. For domain rejections and transport errors (`401`/`404`/`429`/`500`) this is a stable, machine-readable snake_case identifier that is part of the API contract and safe to branch on, e.g. `insufficient_margin`, `insufficient_balance`, `order_not_found`, `reduce_only_invalid`, `price_outside_bounds`, `position_not_found`, `position_exists`, `open_orders_exist`, `invalid_margin_mode`, `invalid_margin_amount`, `margin_below_required_initial`, `account_liquidating`, `instrument_close_only`, `instrument_settled`, `settlement_price_unavailable`, `settlement_insurance_insufficient`, `settlement_invalid_state`, `settlement_close_only_required`, `unauthorized`, `not_found`. `instrument_close_only` means user orders must reduce an existing position; `instrument_settled` is permanent. Settlement readiness errors leave the instrument and accounts unchanged. For `400` it is a human-readable validation detail whose wording may change. See the Error handling guide for the domain identifiers. (Post-only / Fill-or-Kill outcomes are order statuses such as `post_only_rejected`, not rejections.)",
                          "example": "insufficient_margin"
                        },
                        "arts": {
                          "type": "integer",
                          "description": "Gateway arrival timestamp captured at handler entry, in Unix milliseconds.",
                          "example": 1767225600000
                        },
                        "ts": {
                          "type": "integer",
                          "description": "decision time in Unix milliseconds: terminal event time for event-backed outcomes, gateway decision time otherwise",
                          "example": 1767225600000
                        },
                        "ref": {
                          "type": "string",
                          "description": "Unique server-generated rejection reference. Include this value when asking support to locate the corresponding structured rejection trace.",
                          "example": "g-0011223344556"
                        }
                      }
                    }
                  ]
                }
              }
            },
            "required": ["data"]
          },
          "examples": [
            {
              "name": "UnsubscribeResponse Example",
              "payload": {
                "data": []
              }
            }
          ]
        },
        "Update": {
          "name": "TpslUpdate",
          "title": "Update",
          "summary": "TP/SL lifecycle transitions for authenticated users",
          "contentType": "application/json",
          "payload": {
            "title": "TP/SL Update",
            "description": "A lifecycle transition for one of the authenticated account's TP/SL legs, one frame per transition. The frame carries only the new state; read the leg's full order, including its live trigger price, from open orders.",
            "type": "object",
            "properties": {
              "ch": {
                "type": "string",
                "description": "Channel name for push data. Parameterized channels include the instrument ID (e.g. \"trades::1\", \"book::1\", \"klines::1::1m\", \"tickers::all\"). Most private channels use plain names (e.g. \"fills\", \"orders\"). TP/SL updates are the exception: they are suffixed with the authenticated account's numeric ID (e.g. \"tpsl::12345\"), so match them on the \"tpsl::\" prefix. Subscribe and unsubscribe requests still use the bare \"tpsl\".",
                "example": "trades::1"
              },
              "ts": {
                "description": "Server send time, Unix milliseconds",
                "type": "integer",
                "example": 1767225600000
              },
              "ets": {
                "type": "integer",
                "description": "Event timestamp — the newest event this update reflects, in Unix milliseconds. Distinct from `ts`, which is the server send time; `ts - ets` is time spent inside the exchange after the event. `ets=0` means no event horizon is attested, and consumers must treat the horizon as unknown.",
                "example": 1767225600000
              },
              "sq": {
                "type": "integer",
                "description": "Sequence number",
                "example": 1234567890
              },
              "data": {
                "type": "object",
                "required": ["oid", "st"],
                "properties": {
                  "oid": {
                    "type": "integer",
                    "description": "Order ID",
                    "example": 1234567890
                  },
                  "st": {
                    "type": "string",
                    "enum": [
                      "untriggered",
                      "armed",
                      "activated",
                      "cancelled",
                      "expired"
                    ],
                    "description": "New state of the leg. `untriggered`: accepted and waiting for its parent order to fill. `armed`: live and watching its trigger. `activated`: a trailing stop reached its activation price and started trailing. `cancelled`: cancelled by the account. `expired`: left the book for any other reason, including firing; `reason` says which."
                  },
                  "reason": {
                    "type": "string",
                    "description": "Why the leg left the book. Present only when `st` is `expired`. One of `triggered`, `parent_cancelled`, `position_closed`, `position_flipped`, `good_til_time_elapsed`, `reduce_only_invalid_at_trigger`, `instrument_close_only`, `instrument_settled` or `unknown`. Treat other values as `unknown`."
                  }
                }
              }
            },
            "required": ["ch", "ts", "ets", "sq", "data"]
          },
          "examples": [
            {
              "name": "Leg armed",
              "payload": {
                "ch": "tpsl::12345",
                "ts": 1767225600002,
                "ets": 1767225600000,
                "sq": 1234567890,
                "data": {
                  "oid": 1234567890,
                  "st": "armed"
                }
              }
            },
            {
              "name": "Leg triggered",
              "payload": {
                "ch": "tpsl::12345",
                "ts": 1767225660002,
                "ets": 1767225660000,
                "sq": 1234568012,
                "data": {
                  "oid": 1234567890,
                  "st": "expired",
                  "reason": "triggered"
                }
              }
            }
          ]
        }
      }
    }
  },
  "operations": {
    "PingSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/ping"
      },
      "summary": "Send ping",
      "messages": [
        {
          "$ref": "#/channels/ping/messages/Request"
        }
      ]
    },
    "PingReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/ping"
      },
      "summary": "Pong response",
      "messages": [
        {
          "$ref": "#/channels/ping/messages/Response"
        }
      ]
    },
    "PlaceOrdersSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/placeOrders"
      },
      "summary": "Submit new orders",
      "messages": [
        {
          "$ref": "#/channels/placeOrders/messages/Request"
        }
      ]
    },
    "PlaceOrdersReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/placeOrders"
      },
      "summary": "Order ACK response",
      "messages": [
        {
          "$ref": "#/channels/placeOrders/messages/Response"
        }
      ]
    },
    "CancelOrdersSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/cancelOrders"
      },
      "summary": "Cancel orders",
      "messages": [
        {
          "$ref": "#/channels/cancelOrders/messages/Request"
        }
      ]
    },
    "CancelOrdersReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/cancelOrders"
      },
      "summary": "Cancel response",
      "messages": [
        {
          "$ref": "#/channels/cancelOrders/messages/Response"
        }
      ]
    },
    "CancelOrdersCOIDSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/cancelOrdersCOID"
      },
      "summary": "Cancel orders by client order ID",
      "messages": [
        {
          "$ref": "#/channels/cancelOrdersCOID/messages/Request"
        }
      ]
    },
    "CancelOrdersCOIDReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/cancelOrdersCOID"
      },
      "summary": "Cancel by client order ID response",
      "messages": [
        {
          "$ref": "#/channels/cancelOrdersCOID/messages/Response"
        }
      ]
    },
    "CancelAllSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/cancelAll"
      },
      "summary": "Cancel all open orders",
      "messages": [
        {
          "$ref": "#/channels/cancelAll/messages/Request"
        }
      ]
    },
    "CancelAllReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/cancelAll"
      },
      "summary": "Cancel all orders response",
      "messages": [
        {
          "$ref": "#/channels/cancelAll/messages/Response"
        }
      ]
    },
    "AutoCancelSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/autoCancel"
      },
      "summary": "Set or clear auto-cancel",
      "messages": [
        {
          "$ref": "#/channels/autoCancel/messages/Request"
        }
      ]
    },
    "AutoCancelReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/autoCancel"
      },
      "summary": "Auto-cancel response",
      "messages": [
        {
          "$ref": "#/channels/autoCancel/messages/Response"
        }
      ]
    },
    "UpdateLeverageSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/updateLeverage"
      },
      "summary": "Update leverage",
      "messages": [
        {
          "$ref": "#/channels/updateLeverage/messages/Request"
        }
      ]
    },
    "UpdateLeverageReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/updateLeverage"
      },
      "summary": "Update leverage response",
      "messages": [
        {
          "$ref": "#/channels/updateLeverage/messages/Response"
        }
      ]
    },
    "UpdateLeveragesSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/updateLeverages"
      },
      "summary": "Update leverage for multiple instruments",
      "messages": [
        {
          "$ref": "#/channels/updateLeverages/messages/Request"
        }
      ]
    },
    "UpdateLeveragesReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/updateLeverages"
      },
      "summary": "Batch leverage update response",
      "messages": [
        {
          "$ref": "#/channels/updateLeverages/messages/Response"
        }
      ]
    },
    "UpdateMarginSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/updateMargin"
      },
      "summary": "Update isolated margin",
      "messages": [
        {
          "$ref": "#/channels/updateMargin/messages/Request"
        }
      ]
    },
    "UpdateMarginReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/updateMargin"
      },
      "summary": "Update isolated margin response",
      "messages": [
        {
          "$ref": "#/channels/updateMargin/messages/Response"
        }
      ]
    },
    "TradesSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/trades"
      },
      "summary": "Subscribe to trades",
      "messages": [
        {
          "$ref": "#/channels/trades/messages/SubscribeRequest"
        }
      ]
    },
    "TradesSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/trades"
      },
      "summary": "Trades subscribe response",
      "messages": [
        {
          "$ref": "#/channels/trades/messages/SubscribeResponse"
        }
      ]
    },
    "TradesUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/trades"
      },
      "summary": "Unsubscribe from trades",
      "messages": [
        {
          "$ref": "#/channels/trades/messages/UnsubscribeRequest"
        }
      ]
    },
    "TradesUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/trades"
      },
      "summary": "Trades unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/trades/messages/UnsubscribeResponse"
        }
      ]
    },
    "TradesUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/trades"
      },
      "summary": "Receive trade updates",
      "messages": [
        {
          "$ref": "#/channels/trades/messages/Update"
        }
      ]
    },
    "BBOSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/bbo"
      },
      "summary": "Subscribe to BBO",
      "messages": [
        {
          "$ref": "#/channels/bbo/messages/SubscribeRequest"
        }
      ]
    },
    "BBOSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/bbo"
      },
      "summary": "BBO subscribe response",
      "messages": [
        {
          "$ref": "#/channels/bbo/messages/SubscribeResponse"
        }
      ]
    },
    "BBOUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/bbo"
      },
      "summary": "Unsubscribe from BBO",
      "messages": [
        {
          "$ref": "#/channels/bbo/messages/UnsubscribeRequest"
        }
      ]
    },
    "BBOUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/bbo"
      },
      "summary": "BBO unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/bbo/messages/UnsubscribeResponse"
        }
      ]
    },
    "BBOUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/bbo"
      },
      "summary": "Receive BBO updates",
      "messages": [
        {
          "$ref": "#/channels/bbo/messages/Update"
        }
      ]
    },
    "BookSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/book"
      },
      "summary": "Subscribe to book",
      "messages": [
        {
          "$ref": "#/channels/book/messages/SubscribeRequest"
        }
      ]
    },
    "BookSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/book"
      },
      "summary": "Book subscribe response",
      "messages": [
        {
          "$ref": "#/channels/book/messages/SubscribeResponse"
        }
      ]
    },
    "BookUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/book"
      },
      "summary": "Unsubscribe from book",
      "messages": [
        {
          "$ref": "#/channels/book/messages/UnsubscribeRequest"
        }
      ]
    },
    "BookUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/book"
      },
      "summary": "Book unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/book/messages/UnsubscribeResponse"
        }
      ]
    },
    "BookUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/book"
      },
      "summary": "Receive book updates",
      "messages": [
        {
          "$ref": "#/channels/book/messages/Update"
        }
      ]
    },
    "KlinesSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/klines"
      },
      "summary": "Subscribe to klines",
      "messages": [
        {
          "$ref": "#/channels/klines/messages/SubscribeRequest"
        }
      ]
    },
    "KlinesSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/klines"
      },
      "summary": "Klines subscribe response",
      "messages": [
        {
          "$ref": "#/channels/klines/messages/SubscribeResponse"
        }
      ]
    },
    "KlinesUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/klines"
      },
      "summary": "Unsubscribe from klines",
      "messages": [
        {
          "$ref": "#/channels/klines/messages/UnsubscribeRequest"
        }
      ]
    },
    "KlinesUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/klines"
      },
      "summary": "Klines unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/klines/messages/UnsubscribeResponse"
        }
      ]
    },
    "KlinesUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/klines"
      },
      "summary": "Receive kline updates",
      "messages": [
        {
          "$ref": "#/channels/klines/messages/Update"
        }
      ]
    },
    "TickersSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/tickers"
      },
      "summary": "Subscribe to tickers",
      "messages": [
        {
          "$ref": "#/channels/tickers/messages/SubscribeRequest"
        }
      ]
    },
    "TickersSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/tickers"
      },
      "summary": "Tickers subscribe response",
      "messages": [
        {
          "$ref": "#/channels/tickers/messages/SubscribeResponse"
        }
      ]
    },
    "TickersUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/tickers"
      },
      "summary": "Unsubscribe from tickers",
      "messages": [
        {
          "$ref": "#/channels/tickers/messages/UnsubscribeRequest"
        }
      ]
    },
    "TickersUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/tickers"
      },
      "summary": "Tickers unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/tickers/messages/UnsubscribeResponse"
        }
      ]
    },
    "TickersUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/tickers"
      },
      "summary": "Receive ticker updates",
      "messages": [
        {
          "$ref": "#/channels/tickers/messages/Update"
        }
      ]
    },
    "StatisticsSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/statistics"
      },
      "summary": "Subscribe to statistics",
      "messages": [
        {
          "$ref": "#/channels/statistics/messages/SubscribeRequest"
        }
      ]
    },
    "StatisticsSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/statistics"
      },
      "summary": "Statistics subscribe response",
      "messages": [
        {
          "$ref": "#/channels/statistics/messages/SubscribeResponse"
        }
      ]
    },
    "StatisticsUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/statistics"
      },
      "summary": "Unsubscribe from statistics",
      "messages": [
        {
          "$ref": "#/channels/statistics/messages/UnsubscribeRequest"
        }
      ]
    },
    "StatisticsUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/statistics"
      },
      "summary": "Statistics unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/statistics/messages/UnsubscribeResponse"
        }
      ]
    },
    "StatisticsUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/statistics"
      },
      "summary": "Receive statistics updates",
      "messages": [
        {
          "$ref": "#/channels/statistics/messages/Update"
        }
      ]
    },
    "AuthSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/auth"
      },
      "summary": "Authenticate connection",
      "messages": [
        {
          "$ref": "#/channels/auth/messages/Request"
        }
      ]
    },
    "AuthReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/auth"
      },
      "summary": "Auth response",
      "messages": [
        {
          "$ref": "#/channels/auth/messages/Response"
        }
      ]
    },
    "FillsSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/fills"
      },
      "summary": "Subscribe to fills",
      "messages": [
        {
          "$ref": "#/channels/fills/messages/SubscribeRequest"
        }
      ]
    },
    "FillsSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/fills"
      },
      "summary": "Fills subscribe response",
      "messages": [
        {
          "$ref": "#/channels/fills/messages/SubscribeResponse"
        }
      ]
    },
    "FillsUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/fills"
      },
      "summary": "Unsubscribe from fills",
      "messages": [
        {
          "$ref": "#/channels/fills/messages/UnsubscribeRequest"
        }
      ]
    },
    "FillsUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/fills"
      },
      "summary": "Fills unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/fills/messages/UnsubscribeResponse"
        }
      ]
    },
    "FillsUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/fills"
      },
      "summary": "Receive fill updates",
      "messages": [
        {
          "$ref": "#/channels/fills/messages/Update"
        }
      ]
    },
    "BackstopSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/backstop"
      },
      "summary": "Subscribe to backstop liquidations",
      "messages": [
        {
          "$ref": "#/channels/backstop/messages/SubscribeRequest"
        }
      ]
    },
    "BackstopSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/backstop"
      },
      "summary": "Backstop subscribe response",
      "messages": [
        {
          "$ref": "#/channels/backstop/messages/SubscribeResponse"
        }
      ]
    },
    "BackstopUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/backstop"
      },
      "summary": "Unsubscribe from backstop liquidations",
      "messages": [
        {
          "$ref": "#/channels/backstop/messages/UnsubscribeRequest"
        }
      ]
    },
    "BackstopUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/backstop"
      },
      "summary": "Backstop unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/backstop/messages/UnsubscribeResponse"
        }
      ]
    },
    "BackstopUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/backstop"
      },
      "summary": "Receive backstop liquidation updates",
      "messages": [
        {
          "$ref": "#/channels/backstop/messages/Update"
        }
      ]
    },
    "OrdersSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/orders"
      },
      "summary": "Subscribe to orders",
      "messages": [
        {
          "$ref": "#/channels/orders/messages/SubscribeRequest"
        }
      ]
    },
    "OrdersSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/orders"
      },
      "summary": "Orders subscribe response",
      "messages": [
        {
          "$ref": "#/channels/orders/messages/SubscribeResponse"
        }
      ]
    },
    "OrdersUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/orders"
      },
      "summary": "Unsubscribe from orders",
      "messages": [
        {
          "$ref": "#/channels/orders/messages/UnsubscribeRequest"
        }
      ]
    },
    "OrdersUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/orders"
      },
      "summary": "Orders unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/orders/messages/UnsubscribeResponse"
        }
      ]
    },
    "OrdersUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/orders"
      },
      "summary": "Receive order updates",
      "messages": [
        {
          "$ref": "#/channels/orders/messages/Update"
        }
      ]
    },
    "FundingSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/funding"
      },
      "summary": "Subscribe to funding",
      "messages": [
        {
          "$ref": "#/channels/funding/messages/SubscribeRequest"
        }
      ]
    },
    "FundingSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/funding"
      },
      "summary": "Funding subscribe response",
      "messages": [
        {
          "$ref": "#/channels/funding/messages/SubscribeResponse"
        }
      ]
    },
    "FundingUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/funding"
      },
      "summary": "Unsubscribe from funding",
      "messages": [
        {
          "$ref": "#/channels/funding/messages/UnsubscribeRequest"
        }
      ]
    },
    "FundingUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/funding"
      },
      "summary": "Funding unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/funding/messages/UnsubscribeResponse"
        }
      ]
    },
    "FundingUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/funding"
      },
      "summary": "Receive funding updates",
      "messages": [
        {
          "$ref": "#/channels/funding/messages/Update"
        }
      ]
    },
    "BalancesSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/balances"
      },
      "summary": "Subscribe to balances",
      "messages": [
        {
          "$ref": "#/channels/balances/messages/SubscribeRequest"
        }
      ]
    },
    "BalancesSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/balances"
      },
      "summary": "Balances subscribe response",
      "messages": [
        {
          "$ref": "#/channels/balances/messages/SubscribeResponse"
        }
      ]
    },
    "BalancesUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/balances"
      },
      "summary": "Unsubscribe from balances",
      "messages": [
        {
          "$ref": "#/channels/balances/messages/UnsubscribeRequest"
        }
      ]
    },
    "BalancesUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/balances"
      },
      "summary": "Balances unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/balances/messages/UnsubscribeResponse"
        }
      ]
    },
    "BalancesUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/balances"
      },
      "summary": "Receive balance updates",
      "messages": [
        {
          "$ref": "#/channels/balances/messages/Update"
        }
      ]
    },
    "PortfolioSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/portfolio"
      },
      "summary": "Subscribe to portfolio",
      "messages": [
        {
          "$ref": "#/channels/portfolio/messages/SubscribeRequest"
        }
      ]
    },
    "PortfolioSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/portfolio"
      },
      "summary": "Portfolio subscribe response",
      "messages": [
        {
          "$ref": "#/channels/portfolio/messages/SubscribeResponse"
        }
      ]
    },
    "PortfolioUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/portfolio"
      },
      "summary": "Unsubscribe from portfolio",
      "messages": [
        {
          "$ref": "#/channels/portfolio/messages/UnsubscribeRequest"
        }
      ]
    },
    "PortfolioUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/portfolio"
      },
      "summary": "Portfolio unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/portfolio/messages/UnsubscribeResponse"
        }
      ]
    },
    "PortfolioUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/portfolio"
      },
      "summary": "Receive portfolio updates",
      "messages": [
        {
          "$ref": "#/channels/portfolio/messages/Update"
        }
      ]
    },
    "DepositsSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/deposits"
      },
      "summary": "Subscribe to deposits",
      "messages": [
        {
          "$ref": "#/channels/deposits/messages/SubscribeRequest"
        }
      ]
    },
    "DepositsSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/deposits"
      },
      "summary": "Deposits subscribe response",
      "messages": [
        {
          "$ref": "#/channels/deposits/messages/SubscribeResponse"
        }
      ]
    },
    "DepositsUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/deposits"
      },
      "summary": "Unsubscribe from deposits",
      "messages": [
        {
          "$ref": "#/channels/deposits/messages/UnsubscribeRequest"
        }
      ]
    },
    "DepositsUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/deposits"
      },
      "summary": "Deposits unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/deposits/messages/UnsubscribeResponse"
        }
      ]
    },
    "DepositsUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/deposits"
      },
      "summary": "Receive deposit updates",
      "messages": [
        {
          "$ref": "#/channels/deposits/messages/Update"
        }
      ]
    },
    "WithdrawalsSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/withdrawals"
      },
      "summary": "Subscribe to withdrawals",
      "messages": [
        {
          "$ref": "#/channels/withdrawals/messages/SubscribeRequest"
        }
      ]
    },
    "WithdrawalsSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/withdrawals"
      },
      "summary": "Withdrawals subscribe response",
      "messages": [
        {
          "$ref": "#/channels/withdrawals/messages/SubscribeResponse"
        }
      ]
    },
    "WithdrawalsUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/withdrawals"
      },
      "summary": "Unsubscribe from withdrawals",
      "messages": [
        {
          "$ref": "#/channels/withdrawals/messages/UnsubscribeRequest"
        }
      ]
    },
    "WithdrawalsUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/withdrawals"
      },
      "summary": "Withdrawals unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/withdrawals/messages/UnsubscribeResponse"
        }
      ]
    },
    "WithdrawalsUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/withdrawals"
      },
      "summary": "Receive withdrawal updates",
      "messages": [
        {
          "$ref": "#/channels/withdrawals/messages/Update"
        }
      ]
    },
    "NotificationsSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/notifications"
      },
      "summary": "Subscribe to notifications",
      "messages": [
        {
          "$ref": "#/channels/notifications/messages/SubscribeRequest"
        }
      ]
    },
    "NotificationsSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/notifications"
      },
      "summary": "Notifications subscribe response",
      "messages": [
        {
          "$ref": "#/channels/notifications/messages/SubscribeResponse"
        }
      ]
    },
    "NotificationsUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/notifications"
      },
      "summary": "Unsubscribe from notifications",
      "messages": [
        {
          "$ref": "#/channels/notifications/messages/UnsubscribeRequest"
        }
      ]
    },
    "NotificationsUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/notifications"
      },
      "summary": "Notifications unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/notifications/messages/UnsubscribeResponse"
        }
      ]
    },
    "NotificationsUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/notifications"
      },
      "summary": "Receive notification updates",
      "messages": [
        {
          "$ref": "#/channels/notifications/messages/Update"
        }
      ]
    },
    "ModifyOrdersCOIDReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/modifyOrdersCOID"
      },
      "summary": "Modify by client order ID response",
      "messages": [
        {
          "$ref": "#/channels/modifyOrdersCOID/messages/Response"
        }
      ]
    },
    "ModifyOrdersCOIDSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/modifyOrdersCOID"
      },
      "summary": "Modify existing orders by client order ID",
      "messages": [
        {
          "$ref": "#/channels/modifyOrdersCOID/messages/Request"
        }
      ]
    },
    "ModifyOrdersReceive": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/modifyOrders"
      },
      "summary": "Modify order response",
      "messages": [
        {
          "$ref": "#/channels/modifyOrders/messages/Response"
        }
      ]
    },
    "ModifyOrdersSend": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/modifyOrders"
      },
      "summary": "Modify existing orders",
      "messages": [
        {
          "$ref": "#/channels/modifyOrders/messages/Request"
        }
      ]
    },
    "BuilderFillsSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/builderFills"
      },
      "summary": "Subscribe to fills",
      "messages": [
        {
          "$ref": "#/channels/builderFills/messages/SubscribeRequest"
        }
      ]
    },
    "BuilderFillsSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/builderFills"
      },
      "summary": "BuilderFills subscribe response",
      "messages": [
        {
          "$ref": "#/channels/builderFills/messages/SubscribeResponse"
        }
      ]
    },
    "BuilderFillsUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/builderFills"
      },
      "summary": "Unsubscribe from fills",
      "messages": [
        {
          "$ref": "#/channels/builderFills/messages/UnsubscribeRequest"
        }
      ]
    },
    "BuilderFillsUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/builderFills"
      },
      "summary": "BuilderFills unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/builderFills/messages/UnsubscribeResponse"
        }
      ]
    },
    "BuilderFillsUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/builderFills"
      },
      "summary": "Receive fill updates",
      "messages": [
        {
          "$ref": "#/channels/builderFills/messages/Update"
        }
      ]
    },
    "TpslSubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/tpsl"
      },
      "summary": "Subscribe to TP/SL updates",
      "messages": [
        {
          "$ref": "#/channels/tpsl/messages/SubscribeRequest"
        }
      ]
    },
    "TpslSubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/tpsl"
      },
      "summary": "TP/SL subscribe response",
      "messages": [
        {
          "$ref": "#/channels/tpsl/messages/SubscribeResponse"
        }
      ]
    },
    "TpslUnsubscribe": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/tpsl"
      },
      "summary": "Unsubscribe from TP/SL updates",
      "messages": [
        {
          "$ref": "#/channels/tpsl/messages/UnsubscribeRequest"
        }
      ]
    },
    "TpslUnsubscribeResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/tpsl"
      },
      "summary": "TP/SL unsubscribe response",
      "messages": [
        {
          "$ref": "#/channels/tpsl/messages/UnsubscribeResponse"
        }
      ]
    },
    "TpslUpdate": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/tpsl"
      },
      "summary": "Receive TP/SL updates",
      "messages": [
        {
          "$ref": "#/channels/tpsl/messages/Update"
        }
      ]
    }
  }
}
