{
  "openapi": "3.1.0",
  "info": {
    "title": "Papertrade Explorer API (unofficial)",
    "version": "0.2.0",
    "description": "Unofficial, not affiliated with Papertrade. High leverage can lose your whole margin. Read-only: nothing here signs, sends or places anything. Every operation is read-only.",
    "license": {
      "name": "Apache-2.0",
      "identifier": "Apache-2.0"
    },
    "contact": {
      "name": "nirholas",
      "url": "https://github.com/nirholas/papertrade-explorer"
    }
  },
  "servers": [
    {
      "url": "https://papertrade-explorer.pages.dev"
    }
  ],
  "externalDocs": {
    "description": "Documentation",
    "url": "https://papertrade-explorer.pages.dev/docs/"
  },
  "tags": [
    {
      "name": "mcp",
      "description": "Model Context Protocol"
    },
    {
      "name": "tools",
      "description": "REST mirror of the MCP tools"
    }
  ],
  "paths": {
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "MCP Streamable HTTP endpoint (stateless JSON-RPC 2.0, batches accepted)",
        "tags": [
          "mcp"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/JsonRpcRequest"
                  },
                  {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "$ref": "#/components/schemas/JsonRpcRequest"
                    }
                  }
                ]
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response, or one SSE message event when Accept is only text/event-stream.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted. No body."
          },
          "400": {
            "description": "Parse or request error."
          },
          "413": {
            "description": "Body larger than 64 KiB."
          },
          "429": {
            "description": "Rate limit hit."
          }
        }
      },
      "get": {
        "operationId": "mcpInfo",
        "summary": "JSON description of the MCP server",
        "tags": [
          "mcp"
        ],
        "responses": {
          "200": {
            "description": "Server description.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "description": "Returned when Accept is text/event-stream."
          }
        }
      }
    },
    "/api/tools/search": {
      "post": {
        "operationId": "search",
        "summary": "Search wallets, transactions, intents, positions and names",
        "description": "Classify an unknown string and resolve it. A 0x address returns a wallet summary, a 0x 32-byte hash is resolved against HyperEVM to tell a settlement transaction from an intent id (and returns a decoded preview), a bare number is a position id, and anything else searches leaderboard names. The result names the follow-up tool to call.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "query": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128,
                    "description": "Address, transaction hash, intent id, position id or part of a leaderboard name."
                  }
                },
                "required": [
                  "query"
                ],
                "additionalProperties": false
              },
              "example": {
                "query": "0x67891c4b5d4474ffcab2e09b8dfa3d4c4236828c"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "enum": [
                        "wallet",
                        "transaction",
                        "intent",
                        "position",
                        "leaderboard-name",
                        "empty"
                      ]
                    },
                    "value": {
                      "type": "string"
                    },
                    "next_tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "kind",
                    "value"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/get_wallet": {
      "post": {
        "operationId": "get_wallet",
        "summary": "Look up a wallet",
        "description": "Balance sheet of one Papertrade wallet: balance, queued funds, locked funds, available funds, open position and pending operation counts, PAPER held and staked with pending staking rewards, lifetime deposits, withdrawals, realized PnL and fees, active session keys, and leaderboard rank and PnL per window (24h, 7d, 30d, all).\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$",
                    "description": "Wallet address: 0x followed by 40 hex characters. Case-insensitive."
                  }
                },
                "required": [
                  "address"
                ],
                "additionalProperties": false
              },
              "example": {
                "address": "0x67891c4b5d4474ffcab2e09b8dfa3d4c4236828c"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "leaderboard_name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "balance_usd": {
                      "type": "number"
                    },
                    "queued_usd": {
                      "type": "number"
                    },
                    "locked_usd": {
                      "type": "number"
                    },
                    "available_usd": {
                      "type": "number"
                    },
                    "open_positions": {
                      "type": "integer"
                    },
                    "pending_operations": {
                      "type": "integer"
                    },
                    "paper": {
                      "type": "object"
                    },
                    "lifetime": {
                      "type": "object"
                    },
                    "session_keys": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "ranks": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "links": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "address",
                    "balance_usd",
                    "open_positions"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/get_positions": {
      "post": {
        "operationId": "get_positions",
        "summary": "Open positions valued at the live mark",
        "description": "Open positions of a wallet valued at the live Papertrade mark (the Hyperliquid BBO mid): side, leverage, margin, notional, entry, mark, bust (liquidation) price, unrealized PnL before close-side haircut, distance to bust and a risk band. Totals included. Pass position_id to fetch one position; if it is already closed the closed-trade record is returned.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$",
                    "description": "Wallet address: 0x followed by 40 hex characters. Case-insensitive."
                  },
                  "position_id": {
                    "type": "string",
                    "pattern": "^\\d{1,12}$",
                    "description": "Optional position id to narrow to one position."
                  }
                },
                "required": [
                  "address"
                ],
                "additionalProperties": false
              },
              "example": {
                "address": "0x67891c4b5d4474ffcab2e09b8dfa3d4c4236828c"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "marks": {
                      "type": "object",
                      "description": "Live mark price per market symbol."
                    },
                    "positions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "totals": {
                      "type": "object"
                    },
                    "closed": {
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "address",
                    "positions",
                    "totals"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/get_intents": {
      "post": {
        "operationId": "get_intents",
        "summary": "Pending intents of a wallet",
        "description": "Intents the Papertrade relayer has accepted for a wallet and not yet settled on-chain (queued opens, closes, withdrawals, stakes, claims, session keys), each with its intent id, action, acceptance time and deadline, plus the outcome of the most recent intents reported by the stream. Use lookup_intent to follow one id.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$",
                    "description": "Wallet address: 0x followed by 40 hex characters. Case-insensitive."
                  }
                },
                "required": [
                  "address"
                ],
                "additionalProperties": false
              },
              "example": {
                "address": "0x67891c4b5d4474ffcab2e09b8dfa3d4c4236828c"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "pending": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "address",
                    "pending",
                    "count"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/lookup_intent": {
      "post": {
        "operationId": "lookup_intent",
        "summary": "Follow one intent id",
        "description": "Where a signed intent is: in the live trade feed, pending in the relayer queue (needs the wallet), or settled on HyperEVM. Scans the most recent blocks (about 6000, roughly 100 minutes) for the BatchExecutor event and, if found, returns the settling transaction, the decoded intent, signature verification and whether the call executed. Older intents are found through get_trade_history.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "intent_id": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{64}$",
                    "description": "32-byte hash: 0x followed by 64 hex characters."
                  },
                  "wallet": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$",
                    "description": "Optional wallet that signed the intent. Enables the relayer queue check."
                  }
                },
                "required": [
                  "intent_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "intent_id": "0xa45bce0d4543bb7d21c581dfab0a42deb52fc0233e22d34f7c5c5e87250742b2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "intent_id": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "settled",
                        "pending",
                        "seen_in_feed",
                        "not_found"
                      ]
                    },
                    "feed": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "pending": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "settlement": {
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "intent_id",
                    "state"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/decode_transaction": {
      "post": {
        "operationId": "decode_transaction",
        "summary": "Decode a HyperEVM settlement transaction",
        "description": "Fetch a HyperEVM transaction and decode BatchExecutor calldata into the intents it carried: action, wallet, session-key signer, decoded fields (market, side, size, leverage, position ids, amounts), intent id, whether the signature recomputes to the recorded intent id, and whether each call executed. A transaction that is not a Papertrade batch is reported as such.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tx_hash": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{64}$",
                    "description": "32-byte hash: 0x followed by 64 hex characters."
                  }
                },
                "required": [
                  "tx_hash"
                ],
                "additionalProperties": false
              },
              "example": {
                "tx_hash": "0x57c85e286520d205709f1fce287fce8944322e0e43155062efeac931fcb01a1a"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tx_hash": {
                      "type": "string"
                    },
                    "found": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "block_number": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "is_batch": {
                      "type": "boolean"
                    },
                    "intents": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "tx_hash",
                    "found"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/get_leaderboard": {
      "post": {
        "operationId": "get_leaderboard",
        "summary": "Ranked wallets",
        "description": "Ranked Papertrade wallets for a window, 25 per page, sortable, with an optional name search. Rank is the true 1-based rank. PnL and volume are USD numbers.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "window": {
                    "type": "string",
                    "enum": [
                      "24h",
                      "7d",
                      "30d",
                      "all"
                    ],
                    "default": "24h"
                  },
                  "sort_key": {
                    "type": "string",
                    "enum": [
                      "totalWindowedPnl",
                      "realizedPnl",
                      "currentUnrealizedPnl",
                      "currentBalance",
                      "currentQueued",
                      "currentOpenNotional",
                      "totalVolume",
                      "paperTotal",
                      "currentOpenPositionCount"
                    ],
                    "default": "totalWindowedPnl"
                  },
                  "sort_dir": {
                    "type": "string",
                    "enum": [
                      "asc",
                      "desc"
                    ],
                    "default": "desc"
                  },
                  "page": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000,
                    "default": 0,
                    "description": "0-based page index."
                  },
                  "query": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional leaderboard name or address fragment."
                  }
                },
                "required": [],
                "additionalProperties": false
              },
              "example": {
                "window": "24h",
                "page": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "window": {
                      "type": "string"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "total_accounts": {
                      "type": "integer"
                    },
                    "accounts": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "window",
                    "page",
                    "accounts"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/get_trade_history": {
      "post": {
        "operationId": "get_trade_history",
        "summary": "Closed trades of a wallet",
        "description": "Closed and liquidated trades of a wallet, newest first, 75 per page, with net PnL (adjusted PnL minus fees paid), entry and exit, leverage, PAPER minted and the settling transaction. Use the returned next_cursor for the next page.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "pattern": "^0x[0-9a-fA-F]{40}$",
                    "description": "Wallet address: 0x followed by 40 hex characters. Case-insensitive."
                  },
                  "filter": {
                    "type": "string",
                    "enum": [
                      "all",
                      "losses"
                    ],
                    "default": "all"
                  },
                  "cursor": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "next_cursor from a previous call."
                  }
                },
                "required": [
                  "address"
                ],
                "additionalProperties": false
              },
              "example": {
                "address": "0x67891c4b5d4474ffcab2e09b8dfa3d4c4236828c"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "trades": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "address",
                    "trades"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/tools/get_protocol_overview": {
      "post": {
        "operationId": "get_protocol_overview",
        "summary": "Protocol and market overview",
        "description": "Market-wide state: value locked, LP, lifetime volume, open positions, PAPER supply and staked, fees, per-market live mark, open interest in USD against its cap, max leverage and whether each market is openable, whether trading is paused, and the latest trades feed.\n\nRead-only. Same code path as MCP tools/call.",
        "tags": [
          "tools"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recent_trades": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 50,
                    "default": 10,
                    "description": "How many latest trades to include."
                  }
                },
                "required": [],
                "additionalProperties": false
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tvl_usd": {
                      "type": "number"
                    },
                    "markets": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "recent_trades": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "trading_paused": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "tvl_usd",
                    "markets"
                  ],
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer"
            ]
          },
          "method": {
            "type": "string"
          },
          "params": {
            "type": "object"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
