{
  "openapi": "3.1.0",
  "info": {
    "title": "Papertrade liquidations heatmap API",
    "version": "0.2.0",
    "description": "Unofficial, not affiliated with Papertrade. Liquidation map for BTC and ETH built from the largest open Papertrade positions. Every bust price is recomputed with the papertrade-sdk and compared with the API value. High leverage can lose your whole margin.",
    "license": {
      "name": "Apache-2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0"
    }
  },
  "servers": [
    {
      "url": "https://papertrade-liquidations.pages.dev"
    }
  ],
  "paths": {
    "/api/heatmap": {
      "get": {
        "operationId": "getHeatmap",
        "summary": "Liquidation heatmap for one market",
        "description": "Responses are cached for 10 seconds (x-cache: HIT or MISS). Wallet snapshots behind the response are refreshed a few at a time because the upstream stream endpoint is rate limited per IP; see the freshness field.",
        "parameters": [
          {
            "name": "market",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "BTC",
                "ETH"
              ],
              "default": "BTC"
            }
          },
          {
            "name": "bucket",
            "in": "query",
            "description": "Bucket size in dollars. Omit for an automatic size (about 0.05% of the mark price).",
            "schema": {
              "type": "number",
              "minimum": 0.0001,
              "maximum": 1000000
            }
          },
          {
            "name": "wallets",
            "in": "query",
            "description": "How many of the largest holders to include.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 40
            }
          },
          {
            "name": "cascade",
            "in": "query",
            "description": "Price move in percent for the cascade figure, both directions.",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Heatmap",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Heatmap"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or unknown parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Upstream unavailable or warming up",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcpRequest",
        "summary": "MCP Streamable HTTP endpoint (stateless JSON-RPC 2.0)",
        "description": "Model Context Protocol server. Methods: initialize, notifications/initialized, ping, tools/list, tools/call, resources/list, prompts/list. Accepts a single request or a batch of up to 5. Replies as JSON, or as one SSE message event when Accept is only text/event-stream. All tools are read-only.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/JsonRpcRequest"
                  },
                  {
                    "type": "array",
                    "maxItems": 5,
                    "items": {
                      "$ref": "#/components/schemas/JsonRpcRequest"
                    }
                  }
                ]
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": {
                  "name": "get_closest_to_bust",
                  "arguments": {
                    "market": "BTC",
                    "limit": 3
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (or SSE stream with one message event).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted, no body."
          },
          "413": {
            "description": "Body larger than 64 KB."
          },
          "415": {
            "description": "Content-Type must be application/json."
          },
          "429": {
            "description": "Rate limit of 30 requests per minute exceeded. See Retry-After."
          }
        }
      },
      "get": {
        "operationId": "mcpInfo",
        "summary": "JSON description of the MCP server",
        "responses": {
          "200": {
            "description": "Server description with links.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "description": "Returned when Accept is text/event-stream. Allow: POST."
          }
        }
      },
      "delete": {
        "operationId": "mcpDelete",
        "summary": "Not supported (stateless server)",
        "responses": {
          "405": {
            "description": "Method not allowed. Allow: POST."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "const": false
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Bucket": {
        "type": "object",
        "properties": {
          "lo": {
            "type": "number"
          },
          "hi": {
            "type": "number"
          },
          "mid": {
            "type": "number"
          },
          "longNotional": {
            "type": "number",
            "description": "USD notional of longs busting in this bucket"
          },
          "shortNotional": {
            "type": "number",
            "description": "USD notional of shorts busting in this bucket"
          },
          "longCount": {
            "type": "integer"
          },
          "shortCount": {
            "type": "integer"
          }
        }
      },
      "Heatmap": {
        "type": "object",
        "required": [
          "ok",
          "market",
          "markPrice",
          "asOfMs",
          "bucketUsd",
          "coverage",
          "totals",
          "buckets",
          "nearest",
          "diagnostics"
        ],
        "properties": {
          "ok": {
            "const": true
          },
          "market": {
            "type": "string",
            "enum": [
              "BTC",
              "ETH"
            ]
          },
          "markPrice": {
            "type": "number"
          },
          "asOfMs": {
            "type": "integer"
          },
          "bucketUsd": {
            "type": "number"
          },
          "coverage": {
            "type": "object",
            "properties": {
              "wallets": {
                "type": "integer"
              },
              "positions": {
                "type": "integer"
              },
              "trackedNotionalUsd": {
                "type": "number"
              },
              "protocolNotionalUsd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "fraction": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Tracked notional divided by protocol-wide notional, 0 to 1"
              }
            }
          },
          "totals": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "buckets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Bucket"
            }
          },
          "cascade": {
            "type": [
              "object",
              "null"
            ],
            "description": "Notional that busts if price moves the requested percent down (longs) or up (shorts)"
          },
          "nearest": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "wallet": {
                  "type": "string"
                },
                "positionId": {
                  "type": "string"
                },
                "side": {
                  "type": "string",
                  "enum": [
                    "long",
                    "short"
                  ]
                },
                "leverage": {
                  "type": "integer"
                },
                "marginUsd": {
                  "type": "number"
                },
                "notionalUsd": {
                  "type": "number"
                },
                "entry": {
                  "type": "number"
                },
                "bust": {
                  "type": "number"
                },
                "distancePercent": {
                  "type": "number"
                },
                "distanceUsd": {
                  "type": "number"
                }
              }
            }
          },
          "protocol": {
            "type": [
              "object",
              "null"
            ],
            "description": "The protocol-wide liquidation map published by the Papertrade API, in dollars"
          },
          "diagnostics": {
            "type": "object",
            "properties": {
              "positions": {
                "type": "integer"
              },
              "mismatches": {
                "type": "integer",
                "description": "Positions whose SDK-recomputed bust price differs from the API value"
              },
              "wallets": {
                "type": "integer"
              },
              "failedWallets": {
                "type": "integer"
              }
            }
          },
          "freshness": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "refreshed": {
                "type": "integer"
              },
              "cached": {
                "type": "integer"
              },
              "missing": {
                "type": "integer"
              },
              "oldestMs": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "newestMs": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "initialize",
              "notifications/initialized",
              "ping",
              "tools/list",
              "tools/call",
              "resources/list",
              "prompts/list"
            ]
          },
          "params": {
            "type": "object"
          }
        }
      }
    }
  }
}
