{
  "openapi": "3.1.0",
  "info": {
    "title": "LiberX Gateway API",
    "version": "0.1.0-testnet",
    "description": "Public API surface served by the LiberX gateway. Authentication is SIWE-based; trading endpoints additionally require a session-key Ed25519 signature.",
    "contact": {
      "name": "LiberX core",
      "url": "https://liberx.xyz",
      "email": "core@liberx.xyz"
    },
    "license": {
      "name": "Apache-2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0"
    }
  },
  "servers": [
    { "url": "https://api.liberx.xyz/v1", "description": "Testnet (public)" }
  ],
  "tags": [
    { "name": "auth", "description": "SIWE sign-in and session-key rotation." },
    { "name": "markets", "description": "Market catalog and reference data." },
    { "name": "trading", "description": "Place, cancel and modify orders." },
    { "name": "account", "description": "Positions, balances, fills." },
    { "name": "bridge", "description": "Deposits, withdrawals, attestations." }
  ],
  "components": {
    "securitySchemes": {
      "bearer": { "type": "http", "scheme": "bearer" }
    },
    "schemas": {
      "Side": { "type": "string", "enum": ["long", "short"] },
      "OrderType": { "type": "string", "enum": ["market", "limit", "stop"] },
      "PlaceOrderBody": {
        "type": "object",
        "required": ["symbol", "side", "type", "margin", "leverage", "nonce"],
        "properties": {
          "symbol": { "type": "string", "example": "BTCUSD" },
          "side": { "$ref": "#/components/schemas/Side" },
          "type": { "$ref": "#/components/schemas/OrderType" },
          "margin": { "type": "number", "example": 1000 },
          "leverage": { "type": "integer", "example": 10 },
          "price": { "type": "number", "nullable": true, "example": 67450.5 },
          "reduceOnly": { "type": "boolean", "default": false },
          "postOnly": { "type": "boolean", "default": false },
          "nonce": { "type": "integer", "example": 17 }
        }
      },
      "PreconfirmAck": {
        "type": "object",
        "properties": {
          "ackNonce": { "type": "string" },
          "filledSize": { "type": "number" },
          "avgFillPrice": { "type": "number" },
          "feePaid": { "type": "number" },
          "positionAfter": {
            "type": "object",
            "properties": {
              "size": { "type": "number" },
              "avgEntry": { "type": "number" },
              "unrealizedPnl": { "type": "number" }
            }
          },
          "expectedBlock": { "type": "integer" },
          "elapsedMs": { "type": "number", "example": 2.4 }
        }
      }
    }
  },
  "security": [{ "bearer": [] }],
  "paths": {
    "/auth/siwe": {
      "post": {
        "tags": ["auth"],
        "summary": "Exchange a SIWE signature for a bearer token.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["message", "signature", "sessionKey"],
                "properties": {
                  "message": { "type": "string" },
                  "signature": { "type": "string" },
                  "sessionKey": { "type": "string", "description": "secp256k1 pubkey hex." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bearer issued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": { "type": "string" },
                    "expiresAt": { "type": "integer" }
                  }
                }
              }
            }
          },
          "401": { "description": "Invalid signature." }
        }
      }
    },
    "/auth/rotate": {
      "post": {
        "tags": ["auth"],
        "summary": "Rotate the active session key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["newSessionKey"],
                "properties": { "newSessionKey": { "type": "string" } }
              }
            }
          }
        },
        "responses": { "200": { "description": "Rotated." } }
      }
    },
    "/markets": {
      "get": {
        "tags": ["markets"],
        "summary": "List active perpetual markets.",
        "security": [],
        "responses": {
          "200": {
            "description": "Array of markets.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "symbol": { "type": "string" },
                      "base": { "type": "string" },
                      "quote": { "type": "string" },
                      "maxLeverage": { "type": "integer" },
                      "tickSize": { "type": "number" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/markets/{symbol}/book": {
      "get": {
        "tags": ["markets"],
        "summary": "Snapshot of the top N levels of the book.",
        "security": [],
        "parameters": [
          { "name": "symbol", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "depth", "in": "query", "schema": { "type": "integer", "default": 50 } }
        ],
        "responses": { "200": { "description": "Snapshot." } }
      }
    },
    "/orders": {
      "post": {
        "tags": ["trading"],
        "summary": "Place a perpetual order.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/PlaceOrderBody" } }
          }
        },
        "responses": {
          "200": {
            "description": "Preconfirm acknowledgement.",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/PreconfirmAck" } }
            }
          },
          "400": { "description": "Validation error." },
          "429": { "description": "Rate limited." }
        }
      }
    },
    "/orders/{id}/cancel": {
      "post": {
        "tags": ["trading"],
        "summary": "Cancel a resting order.",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Canceled." } }
      }
    },
    "/positions": {
      "get": {
        "tags": ["account"],
        "summary": "Get the caller's open positions.",
        "responses": { "200": { "description": "Array of positions." } }
      }
    },
    "/fills": {
      "get": {
        "tags": ["account"],
        "summary": "Get recent fills.",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 100 } }
        ],
        "responses": { "200": { "description": "Array of fills." } }
      }
    },
    "/bridge/deposit": {
      "post": {
        "tags": ["bridge"],
        "summary": "Register a bridge deposit for attestation.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["chain", "txHash", "token"],
                "properties": {
                  "chain": { "type": "string", "enum": ["ethereum", "arbitrum", "tron"] },
                  "txHash": { "type": "string" },
                  "token": { "type": "string", "enum": ["USDC", "USDT"] }
                }
              }
            }
          }
        },
        "responses": { "202": { "description": "Queued for attestation." } }
      }
    }
  }
}
