{
  "openapi": "3.1.0",
  "info": {
    "title": "MOX API",
    "version": "0.1.0",
    "summary": "Perpetual futures on collectibles, with test USD.",
    "description": "REST API of MOX, a Hyperliquid-style perpetuals exchange for collectibles (MTG, Pokémon, One Piece, CS2 skins, index baskets). All money is test USD. Decimals are strings, times are unix milliseconds, sizes are units of the item. Contract: docs/API.md and docs/MCP.md. Rate limits: 120 requests a minute per token, 6,000 a minute per IP for anonymous calls, and 20 order placements a minute per account; 429s carry Retry-After. Public market data is cached (Cache-Control, ETag) and refreshed at most 4 times a second."
  },
  "servers": [
    {
      "url": "/",
      "description": "This host (the site proxies the agent paths; the API serves everything)."
    }
  ],
  "tags": [
    {
      "name": "markets"
    },
    {
      "name": "oracle"
    },
    {
      "name": "account"
    },
    {
      "name": "trading"
    },
    {
      "name": "api-keys"
    },
    {
      "name": "realtime"
    },
    {
      "name": "mcp"
    },
    {
      "name": "discovery"
    },
    {
      "name": "oauth"
    },
    {
      "name": "system"
    }
  ],
  "security": [],
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Health check",
        "operationId": "health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/markets": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "List markets",
        "operationId": "listMarkets",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "markets": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Market"
                      }
                    }
                  },
                  "required": [
                    "markets"
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/markets/{symbol}": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "Get a market",
        "operationId": "getMarket",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Market"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Market symbol, e.g. \"MTG-LOTUS\"."
          }
        ]
      }
    },
    "/v1/markets/{symbol}/book": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "L2 order book",
        "operationId": "getBook",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/L2Book"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Market symbol, e.g. \"MTG-LOTUS\"."
          },
          {
            "name": "depth",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 200
            },
            "description": "Levels per side."
          }
        ]
      }
    },
    "/v1/markets/{symbol}/trades": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "Recent trades, newest first",
        "operationId": "getTrades",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "trades": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Trade"
                      }
                    }
                  },
                  "required": [
                    "trades"
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Market symbol, e.g. \"MTG-LOTUS\"."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "description": "Default 50, max 200."
          }
        ]
      }
    },
    "/v1/markets/{symbol}/candles": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "Candles, oldest first",
        "operationId": "getCandles",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "candles": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Candle"
                      }
                    }
                  },
                  "required": [
                    "candles"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "OHLC from the mark price, volume from trades. `1d` includes up to 365 days of `backfill` bars before the market's first live day.",
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Market symbol, e.g. \"MTG-LOTUS\"."
          },
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1m",
                "5m",
                "15m",
                "1h",
                "4h",
                "1d"
              ],
              "default": "1m"
            },
            "description": "Candle interval."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 300
            },
            "description": "Default 300, max 1000."
          }
        ]
      }
    },
    "/v1/feed": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "Trades across all markets, newest first",
        "operationId": "getFeed",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "trades": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Trade"
                      }
                    }
                  },
                  "required": [
                    "trades"
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "description": "Default 50, max 200."
          }
        ]
      }
    },
    "/v1/leaderboard": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "PnL leaderboard",
        "operationId": "getLeaderboard",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaderboardRow"
                      }
                    }
                  },
                  "required": [
                    "rows"
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "System accounts are excluded; simulated traders carry sim: true."
      }
    },
    "/v1/sparklines": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "Recent closes of every market, for sparklines (cached ≤ 30 s)",
        "operationId": "getSparklines",
        "description": "One call for every market's sparkline: the last `points` candle closes at `interval`, oldest first; the last point is the open bucket (the live mark). `1d` includes backfill bars before a market's first live day. Recomputed at most every 30 s.",
        "parameters": [
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1m",
                "5m",
                "15m",
                "1h",
                "4h",
                "1d"
              ],
              "default": "1h"
            },
            "description": "Candle interval. Default 1h."
          },
          {
            "name": "points",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 2,
              "maximum": 200,
              "default": 48
            },
            "description": "Closes per market. Default 48, max 200."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sparklines": {
                      "type": "object",
                      "description": "Market symbol → closes (decimal strings), oldest first.",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "required": [
                    "sparklines"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "tags": [
          "markets"
        ],
        "summary": "Platform stats (cached ≤ 5 s)",
        "operationId": "getPlatformStats",
        "description": "24h volume, open interest and trader counts across all markets, each with its simulated share.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformStats"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/oracle/{symbol}": {
      "get": {
        "tags": [
          "oracle"
        ],
        "summary": "Oracle state for a market",
        "operationId": "getOracle",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OracleState"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Market symbol, e.g. \"MTG-LOTUS\"."
          }
        ]
      }
    },
    "/v1/oracle/observations": {
      "get": {
        "tags": [
          "oracle"
        ],
        "summary": "Screened observations, all markets",
        "operationId": "listObservations",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "observations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Observation"
                      }
                    }
                  },
                  "required": [
                    "observations"
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Default 100, max 500."
          },
          {
            "name": "verdict",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "accepted",
                "downweighted",
                "rejected"
              ]
            },
            "description": "Only this verdict."
          }
        ]
      }
    },
    "/v1/session": {
      "post": {
        "tags": [
          "account"
        ],
        "summary": "Start a session",
        "operationId": "createSession",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "Upserts the user; a new user gets a $1,000 test-USD faucet credit (is_new: true).",
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/me": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "Me",
        "operationId": "getMe",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      },
      "patch": {
        "tags": [
          "account"
        ],
        "summary": "Change handle",
        "operationId": "patchMe",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string",
                    "pattern": "^[a-z0-9-]{3,20}$"
                  }
                },
                "required": [
                  "handle"
                ]
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "trade"
      }
    },
    "/v1/account": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "Account summary",
        "operationId": "getAccount",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/account/fills": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "Fills, newest first",
        "operationId": "listFills",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "fills": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Fill"
                      }
                    }
                  },
                  "required": [
                    "fills"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Default 100, max 500."
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/account/orders": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "Orders, newest first",
        "operationId": "listOrders",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  },
                  "required": [
                    "orders"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "filled",
                "cancelled",
                "rejected"
              ]
            },
            "description": "Only this status."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Default 100, max 500."
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/account/funding": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "Funding payments, newest first",
        "operationId": "listFunding",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FundingPayment"
                      }
                    }
                  },
                  "required": [
                    "payments"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Default 100, max 500."
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/account/ledger": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "Ledger, newest first",
        "operationId": "listLedger",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LedgerEntry"
                      }
                    }
                  },
                  "required": [
                    "entries"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Default 100, max 500."
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/account/activity": {
      "get": {
        "tags": [
          "account"
        ],
        "summary": "What this user has traded",
        "operationId": "getActivity",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "read"
      }
    },
    "/v1/orders": {
      "post": {
        "tags": [
          "trading"
        ],
        "summary": "Place an order",
        "operationId": "placeOrder",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "Rejections (422): insufficient_margin, price_band, oi_cap, min_notional, reduce_only, post_only_would_cross, no_liquidity, oracle_stale. 20 placements a minute per account.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlaceOrder"
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "trade"
      },
      "delete": {
        "tags": [
          "trading"
        ],
        "summary": "Cancel all open orders",
        "operationId": "cancelAllOrders",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cancelled": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "cancelled"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Only this market."
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "trade"
      }
    },
    "/v1/orders/{id}": {
      "delete": {
        "tags": [
          "trading"
        ],
        "summary": "Cancel an order",
        "operationId": "cancelOrder",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order": {
                      "$ref": "#/components/schemas/Order"
                    }
                  },
                  "required": [
                    "order"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "trade"
      }
    },
    "/v1/positions/{symbol}/close": {
      "post": {
        "tags": [
          "trading"
        ],
        "summary": "Close a position",
        "operationId": "closePosition",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "Reduce-only market order; default closes the whole position.",
        "parameters": [
          {
            "name": "symbol",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Market symbol, e.g. \"MTG-LOTUS\"."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sz": {
                    "type": "string",
                    "pattern": "^-?\\d+(\\.\\d+)?$",
                    "description": "Units to close (default: all)."
                  }
                },
                "required": []
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "trade"
      }
    },
    "/v1/faucet": {
      "post": {
        "tags": [
          "trading"
        ],
        "summary": "Top up to $1,000 test USD",
        "operationId": "claimFaucet",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "Once per hour (429 faucet_cooldown).",
        "security": [
          {
            "bearer": []
          }
        ],
        "x-mox-scope": "trade"
      }
    },
    "/v1/api-keys": {
      "post": {
        "tags": [
          "api-keys"
        ],
        "summary": "Create an API key",
        "operationId": "createApiKey",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "$ref": "#/components/schemas/ApiKey"
                    },
                    "secret": {
                      "type": "string",
                      "description": "mox_sk_… — shown once."
                    }
                  },
                  "required": [
                    "key",
                    "secret"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "description": "Privy session only (API keys cannot manage API keys). At most 10 per user.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "read",
                        "trade"
                      ]
                    }
                  }
                },
                "required": [
                  "name",
                  "scopes"
                ]
              }
            }
          }
        },
        "security": [
          {
            "privy": []
          }
        ]
      },
      "get": {
        "tags": [
          "api-keys"
        ],
        "summary": "List API keys",
        "operationId": "listApiKeys",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      }
                    }
                  },
                  "required": [
                    "keys"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "privy": []
          }
        ]
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "tags": [
          "api-keys"
        ],
        "summary": "Delete an API key",
        "operationId": "deleteApiKey",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "privy": []
          }
        ]
      }
    },
    "/ws": {
      "get": {
        "tags": [
          "realtime"
        ],
        "summary": "WebSocket",
        "operationId": "websocket",
        "responses": {
          "101": {
            "description": "Switching protocols. Channels: markets, book, trades, feed, candles, oracle, account (see docs/API.md)."
          }
        },
        "description": "Subscribe with {\"op\":\"subscribe\",\"channel\":…}; authenticate the account channel with {\"op\":\"auth\",\"token\":…}."
      }
    },
    "/mcp": {
      "post": {
        "tags": [
          "mcp"
        ],
        "summary": "Public MCP (Streamable HTTP): read-only market tools, no auth.",
        "operationId": "mcpPublicPost",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "JSON-RPC 2.0 request (initialize, tools/list, tools/call, resources/read, …)."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (application/json, or text/event-stream when streamed).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": []
      },
      "get": {
        "tags": [
          "mcp"
        ],
        "summary": "Server-sent event stream (Streamable HTTP).",
        "operationId": "mcpPublicGet",
        "responses": {
          "200": {
            "description": "text/event-stream"
          },
          "405": {
            "description": "Not supported in stateless mode."
          }
        },
        "security": []
      },
      "delete": {
        "tags": [
          "mcp"
        ],
        "summary": "End an MCP session.",
        "operationId": "mcpPublicDelete",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": []
      }
    },
    "/mcp/trade": {
      "post": {
        "tags": [
          "mcp"
        ],
        "summary": "Account MCP: public tools + account (read) and trading (trade) tools. 401 carries WWW-Authenticate: Bearer resource_metadata=….",
        "operationId": "mcpTradePost",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "JSON-RPC 2.0 request (initialize, tools/list, tools/call, resources/read, …)."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (application/json, or text/event-stream when streamed).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "mox:read",
              "mox:trade"
            ]
          }
        ]
      },
      "get": {
        "tags": [
          "mcp"
        ],
        "summary": "Server-sent event stream (Streamable HTTP).",
        "operationId": "mcpTradeGet",
        "responses": {
          "200": {
            "description": "text/event-stream"
          },
          "405": {
            "description": "Not supported in stateless mode."
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "mox:read",
              "mox:trade"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "mcp"
        ],
        "summary": "End an MCP session.",
        "operationId": "mcpTradeDelete",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "oauth": [
              "mox:read",
              "mox:trade"
            ]
          }
        ]
      }
    },
    "/.well-known/mcp.json": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "MCP server card",
        "operationId": "mcpServerCard",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "description": "Name, description, endpoints, auth and tool list."
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "OAuth protected-resource metadata (RFC 9728)",
        "operationId": "protectedResource",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource/mcp/trade": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Protected-resource metadata for /mcp/trade (RFC 9728)",
        "operationId": "protectedResourceTrade",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Authorization-server metadata (RFC 8414)",
        "operationId": "authServerMetadata",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "This document",
        "operationId": "openapi",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/oauth/register": {
      "post": {
        "tags": [
          "oauth"
        ],
        "summary": "Dynamic client registration (RFC 7591)",
        "operationId": "oauthRegister",
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string"
                  },
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "https, or http on loopback."
                    }
                  }
                },
                "required": [
                  "redirect_uris"
                ]
              }
            }
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "tags": [
          "oauth"
        ],
        "summary": "Authorization endpoint",
        "operationId": "oauthAuthorize",
        "responses": {
          "302": {
            "description": "To {SITE}/connect/authorize?login_state=…&client_name=…&scopes=… (or back to redirect_uri with an error)."
          },
          "400": {
            "description": "Unknown client or redirect URI."
          }
        },
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "code"
          },
          {
            "name": "client_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Registered redirect URI."
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "PKCE S256 challenge."
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "S256"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "mox:read mox:trade"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "resource",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "{SITE}/mcp/trade"
          }
        ]
      }
    },
    "/oauth/complete": {
      "post": {
        "tags": [
          "oauth"
        ],
        "summary": "Consent bridge (called by the site with a Privy token)",
        "operationId": "oauthComplete",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "redirect_url": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "redirect_url"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "login_state": {
                    "type": "string"
                  },
                  "approve": {
                    "type": "boolean"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "mox:read",
                        "mox:trade"
                      ]
                    }
                  }
                },
                "required": [
                  "login_state",
                  "approve"
                ]
              }
            }
          }
        },
        "security": [
          {
            "privy": []
          }
        ]
      }
    },
    "/oauth/token": {
      "post": {
        "tags": [
          "oauth"
        ],
        "summary": "Token endpoint (authorization_code with PKCE, refresh_token)",
        "operationId": "oauthToken",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string"
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string"
                  },
                  "refresh_token": {
                    "type": "string"
                  }
                },
                "required": [
                  "grant_type",
                  "client_id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "access_token",
                    "token_type",
                    "expires_in",
                    "refresh_token",
                    "scope"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Category": {
        "type": "string",
        "description": "Collectible category.",
        "enum": [
          "mtg",
          "pokemon",
          "onepiece",
          "cs2"
        ]
      },
      "Kind": {
        "type": "string",
        "description": "Single item or index basket.",
        "enum": [
          "single",
          "index"
        ]
      },
      "OracleStatus": {
        "type": "string",
        "description": "live = a source reported within the staleness window; stale = none did (opening orders are blocked); seed = no live source yet.",
        "enum": [
          "live",
          "stale",
          "seed"
        ]
      },
      "Side": {
        "type": "string",
        "description": "buy = long, sell = short.",
        "enum": [
          "buy",
          "sell"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Machine-readable code, e.g. insufficient_margin, scope_required, rate_limited."
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Constituent": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "image_url": {
            "type": "string"
          },
          "quantity": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Units of this item in one index unit."
          },
          "symbol": {
            "type": "string",
            "description": "Set when the constituent is also listed as a single."
          },
          "price": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "The oracle's current price for this constituent (null before its first observation)."
          }
        },
        "required": [
          "name",
          "image_url",
          "quantity",
          "price"
        ]
      },
      "MarketStats": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "mark_px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "oracle_px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "mid_px": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Null when one side of the book is empty."
          },
          "prev_day_px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Mark 24h ago."
          },
          "day_change_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "day_volume_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "day_volume_sim_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "\"0.0\"–\"100.0\": share of 24h volume where at least one side is a simulated account (market maker, sim trader, vault, fee)."
          },
          "open_interest": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Units, one side."
          },
          "open_interest_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "open_interest_sim_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "\"0.0\"–\"100.0\": share of open interest (position units, both sides) held by simulated accounts."
          },
          "funding_rate": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Predicted hourly rate for the next payment."
          },
          "next_funding_ms": {
            "type": "integer",
            "format": "int64"
          },
          "oracle_status": {
            "$ref": "#/components/schemas/OracleStatus"
          },
          "oracle_updated_ms": {
            "type": "integer",
            "format": "int64"
          }
        },
        "required": [
          "symbol",
          "mark_px",
          "oracle_px",
          "mid_px",
          "prev_day_px",
          "day_change_pct",
          "day_volume_usd",
          "day_volume_sim_pct",
          "open_interest",
          "open_interest_usd",
          "open_interest_sim_pct",
          "funding_rate",
          "next_funding_ms",
          "oracle_status",
          "oracle_updated_ms"
        ]
      },
      "Market": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string",
            "description": "e.g. \"MTG-LOTUS\""
          },
          "name": {
            "type": "string"
          },
          "variant": {
            "type": "string"
          },
          "category": {
            "$ref": "#/components/schemas/Category"
          },
          "kind": {
            "$ref": "#/components/schemas/Kind"
          },
          "image_url": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "max_leverage": {
            "type": "integer"
          },
          "maintenance_margin_ratio": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "1 / (2 × max_leverage)."
          },
          "taker_fee": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Fraction of notional."
          },
          "maker_fee": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Fraction of notional."
          },
          "sz_decimals": {
            "type": "integer",
            "description": "Size precision."
          },
          "tick_size": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Price precision."
          },
          "min_notional": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "USD."
          },
          "oi_cap_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Open-interest cap, USD notional per side."
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "constituents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Constituent"
            }
          },
          "stats": {
            "$ref": "#/components/schemas/MarketStats"
          }
        },
        "required": [
          "symbol",
          "name",
          "variant",
          "category",
          "kind",
          "image_url",
          "description",
          "max_leverage",
          "maintenance_margin_ratio",
          "taker_fee",
          "maker_fee",
          "sz_decimals",
          "tick_size",
          "min_notional",
          "oi_cap_usd",
          "sources",
          "stats"
        ]
      },
      "BookLevel": {
        "type": "object",
        "properties": {
          "px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "n": {
            "type": "integer",
            "description": "Orders at this level."
          }
        },
        "required": [
          "px",
          "sz",
          "n"
        ]
      },
      "L2Book": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "bids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookLevel"
            }
          },
          "asks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookLevel"
            }
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          }
        },
        "required": [
          "symbol",
          "bids",
          "asks",
          "ts"
        ],
        "description": "Bids high→low, asks low→high."
      },
      "Trade": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "buyer": {
            "type": "string",
            "description": "Public handle."
          },
          "seller": {
            "type": "string",
            "description": "Public handle."
          },
          "buyer_sim": {
            "type": "boolean",
            "description": "Simulated account (market maker, sim trader, vault)."
          },
          "seller_sim": {
            "type": "boolean"
          },
          "liquidation": {
            "type": "boolean"
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          }
        },
        "required": [
          "id",
          "symbol",
          "px",
          "sz",
          "side",
          "buyer",
          "seller",
          "buyer_sim",
          "seller_sim",
          "liquidation",
          "ts"
        ],
        "description": "side is the taker side."
      },
      "Candle": {
        "type": "object",
        "properties": {
          "t": {
            "type": "integer",
            "format": "int64",
            "description": "Open time."
          },
          "o": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "h": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "l": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "c": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "v": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Units traded on MOX (\"0\" for backfill)."
          },
          "backfill": {
            "type": "boolean",
            "description": "true = a daily reference-price bar from before MOX listed the market."
          }
        },
        "required": [
          "t",
          "o",
          "h",
          "l",
          "c",
          "v",
          "backfill"
        ]
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "type": {
            "type": "string",
            "enum": [
              "market",
              "limit"
            ]
          },
          "px": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "filled_sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "filled",
              "cancelled",
              "rejected"
            ]
          },
          "reduce_only": {
            "type": "boolean"
          },
          "post_only": {
            "type": "boolean"
          },
          "leverage": {
            "type": "integer"
          },
          "reject_reason": {
            "type": "string"
          },
          "created_ms": {
            "type": "integer",
            "format": "int64"
          },
          "updated_ms": {
            "type": "integer",
            "format": "int64"
          }
        },
        "required": [
          "id",
          "symbol",
          "side",
          "type",
          "px",
          "sz",
          "filled_sz",
          "status",
          "reduce_only",
          "post_only",
          "leverage",
          "created_ms",
          "updated_ms"
        ]
      },
      "Fill": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "fee": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "realized_pnl": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "liquidity": {
            "type": "string",
            "enum": [
              "maker",
              "taker"
            ]
          },
          "liquidation": {
            "type": "boolean"
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          }
        },
        "required": [
          "id",
          "order_id",
          "symbol",
          "side",
          "px",
          "sz",
          "fee",
          "realized_pnl",
          "liquidity",
          "liquidation",
          "ts"
        ]
      },
      "Position": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Signed: + long, − short."
          },
          "entry_px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "mark_px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "notional_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "unrealized_pnl": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "roe_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "leverage": {
            "type": "integer"
          },
          "margin_used": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "liquidation_px": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "funding_since_open": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "+ received, − paid."
          }
        },
        "required": [
          "symbol",
          "sz",
          "entry_px",
          "mark_px",
          "notional_usd",
          "unrealized_pnl",
          "roe_pct",
          "leverage",
          "margin_used",
          "liquidation_px",
          "funding_since_open"
        ]
      },
      "AccountSummary": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Collateral: deposits + realized PnL + funding − fees."
          },
          "account_value": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "unrealized_pnl": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "margin_used": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "maintenance_margin": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "free_collateral": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "positions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Position"
            }
          },
          "open_orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          },
          "faucet_available_ms": {
            "type": "integer",
            "format": "int64",
            "description": "0 = now."
          }
        },
        "required": [
          "balance",
          "account_value",
          "unrealized_pnl",
          "margin_used",
          "maintenance_margin",
          "free_collateral",
          "positions",
          "open_orders",
          "faucet_available_ms"
        ]
      },
      "Me": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "created_ms": {
            "type": "integer",
            "format": "int64"
          },
          "is_new": {
            "type": "boolean"
          },
          "account": {
            "$ref": "#/components/schemas/AccountSummary"
          }
        },
        "required": [
          "user_id",
          "handle",
          "created_ms",
          "is_new",
          "account"
        ]
      },
      "FundingPayment": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          },
          "rate": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Hourly."
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "payment_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "+ received."
          }
        },
        "required": [
          "symbol",
          "ts",
          "rate",
          "sz",
          "payment_usd"
        ]
      },
      "LedgerEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "faucet",
              "fee",
              "realized_pnl",
              "funding",
              "liquidation"
            ]
          },
          "amount_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "symbol": {
            "type": "string"
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          },
          "note": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "kind",
          "amount_usd",
          "ts"
        ]
      },
      "Activity": {
        "type": "object",
        "properties": {
          "markets": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "symbol": {
                  "type": "string"
                },
                "category": {
                  "$ref": "#/components/schemas/Category"
                },
                "kind": {
                  "$ref": "#/components/schemas/Kind"
                },
                "volume_usd": {
                  "type": "string",
                  "pattern": "^-?\\d+(\\.\\d+)?$",
                  "description": "Σ |px × sz| of the user's fills."
                },
                "fills": {
                  "type": "integer"
                },
                "last_traded_ms": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "required": [
                "symbol",
                "category",
                "kind",
                "volume_usd",
                "fills",
                "last_traded_ms"
              ]
            }
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "category": {
                  "$ref": "#/components/schemas/Category"
                },
                "volume_usd": {
                  "type": "string",
                  "pattern": "^-?\\d+(\\.\\d+)?$"
                },
                "fills": {
                  "type": "integer"
                }
              },
              "required": [
                "category",
                "volume_usd",
                "fills"
              ]
            }
          }
        },
        "required": [
          "markets",
          "categories"
        ]
      },
      "LeaderboardRow": {
        "type": "object",
        "properties": {
          "handle": {
            "type": "string"
          },
          "account_value": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "pnl": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "pnl_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "sim": {
            "type": "boolean"
          }
        },
        "required": [
          "handle",
          "account_value",
          "pnl",
          "pnl_pct",
          "sim"
        ]
      },
      "Observation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "item": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "sale",
              "market",
              "listing"
            ]
          },
          "px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "qty": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "observed_ms": {
            "type": "integer",
            "format": "int64"
          },
          "received_ms": {
            "type": "integer",
            "format": "int64"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "accepted",
              "downweighted",
              "rejected"
            ]
          },
          "manipulation_score": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "0..1."
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "model": {
            "type": "string"
          },
          "weight": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          }
        },
        "required": [
          "id",
          "symbol",
          "item",
          "source",
          "kind",
          "px",
          "qty",
          "observed_ms",
          "received_ms",
          "verdict",
          "manipulation_score",
          "reasons",
          "model",
          "weight"
        ]
      },
      "OracleSource": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "last_px": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "last_ms": {
            "type": "integer",
            "format": "int64"
          },
          "ok": {
            "type": "boolean"
          },
          "note": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "last_px",
          "last_ms",
          "ok"
        ]
      },
      "OracleState": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "price": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "target": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$"
          },
          "status": {
            "$ref": "#/components/schemas/OracleStatus"
          },
          "updated_ms": {
            "type": "integer",
            "format": "int64"
          },
          "max_move_bps_per_min": {
            "type": "integer"
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OracleSource"
            }
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ts": {
                  "type": "integer",
                  "format": "int64"
                },
                "px": {
                  "type": "string",
                  "pattern": "^-?\\d+(\\.\\d+)?$"
                }
              },
              "required": [
                "ts",
                "px"
              ]
            }
          },
          "observations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Observation"
            }
          }
        },
        "required": [
          "symbol",
          "price",
          "target",
          "status",
          "updated_ms",
          "max_move_bps_per_min",
          "sources",
          "history",
          "observations"
        ]
      },
      "PlaceOrder": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "type": {
            "type": "string",
            "enum": [
              "market",
              "limit"
            ]
          },
          "sz": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Units; or sz_usd."
          },
          "sz_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Notional in USD, converted at mark (market) or px (limit)."
          },
          "px": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Required for limit."
          },
          "leverage": {
            "type": "integer",
            "description": "1..max_leverage; sets the market's leverage for this user."
          },
          "reduce_only": {
            "type": "boolean"
          },
          "post_only": {
            "type": "boolean"
          },
          "slippage_bps": {
            "type": "integer",
            "description": "Market orders: worst acceptable price vs mark, default 500."
          }
        },
        "required": [
          "symbol",
          "side",
          "type",
          "leverage"
        ]
      },
      "OrderResult": {
        "type": "object",
        "properties": {
          "order": {
            "$ref": "#/components/schemas/Order"
          },
          "fills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Fill"
            }
          }
        },
        "required": [
          "order",
          "fills"
        ]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "e.g. \"mox_sk_AbC1\"."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "trade"
              ]
            }
          },
          "created_ms": {
            "type": "integer",
            "format": "int64"
          },
          "last_used_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "created_ms",
          "last_used_ms"
        ]
      },
      "PlatformStats": {
        "type": "object",
        "description": "Platform-wide 24h volume, open interest and trader counts with their simulated shares.",
        "properties": {
          "day_volume_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "USD."
          },
          "day_volume_sim_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "\"0.0\"–\"100.0\"."
          },
          "open_interest_usd": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "USD."
          },
          "open_interest_sim_pct": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "\"0.0\"–\"100.0\", USD-weighted across markets."
          },
          "traders_24h": {
            "type": "integer",
            "description": "Distinct accounts with a fill in the last 24h (simulated included)."
          },
          "sim_traders_24h": {
            "type": "integer",
            "description": "How many of those are simulated."
          }
        },
        "required": [
          "day_volume_usd",
          "day_volume_sim_pct",
          "open_interest_usd",
          "open_interest_sim_pct",
          "traders_24h",
          "sim_traders_24h"
        ]
      }
    },
    "responses": {
      "Error": {
        "description": "Error envelope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "A Privy access token (full access) or a personal API key mox_sk_… (scopes read / trade; a missing scope returns 403 scope_required)."
      },
      "privy": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "A Privy access token (the web app's session). API keys are refused."
      },
      "oauth": {
        "type": "oauth2",
        "description": "OAuth 2.1 with PKCE for /mcp/trade (dynamic client registration at /oauth/register).",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "/oauth/authorize",
            "tokenUrl": "/oauth/token",
            "refreshUrl": "/oauth/token",
            "scopes": {
              "mox:read": "Read your account, positions, orders and fills.",
              "mox:trade": "Place, cancel and close orders; claim test USD."
            }
          }
        }
      }
    }
  }
}