{
  "openapi": "3.1.0",
  "info": {
    "title": "Pump Data",
    "version": "0.2.0-early-access",
    "summary": "Every pump.fun and PumpSwap trade since pump.fun's first day, for trading agents, by the call.",
    "description": "Every pump.fun bonding-curve trade and every PumpSwap trade since 19 Jan 2024, every mint (including those whose address does not end in \"pump\"), every balance change, and each wallet's record over the whole history. Four calls, paid per call in USDC over x402 on Solana; no account, no key. Early access: these calls are the contract, sign up at / to be told when they answer. Not affiliated with pump.fun. Plain-text overview at /llms.txt.",
    "x-status": "early-access",
    "x-payment": { "protocol": "x402", "asset": "USDC", "network": "solana" }
  },
  "servers": [{ "url": "https://pumpdata.fun", "description": "early access (the page and signup); the calls answer here at launch" }],
  "paths": {
    "/wallets": {
      "post": {
        "operationId": "wallet_records",
        "summary": "What these wallets have been, since pump.fun's first day",
        "description": "Up to 50 wallet addresses in, and optionally the coin they are buying; for each, its class by rule (winner, bot, supply_seller, leader, new) and the numbers behind it: SOL put in and taken out, coins traded, first seen. Records run to the last weekly build and are filled from the live recorder since; the build's date is in the X-Data-As-Of header. $0.01 a call.",
        "x-price-usd": 0.01,
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["addresses"],
          "properties": {
            "addresses": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "type": "string", "description": "a Solana wallet address, base58" } },
            "mint": { "type": "string", "description": "the coin these wallets are buying, base58; new means no record before its creation. Without it, new means no record before today (UTC)" }
          }
        } } } },
        "responses": {
          "200": { "description": "one record per address", "content": { "application/json": { "schema": {
            "type": "object", "additionalProperties": { "$ref": "#/components/schemas/WalletRecord" }
          } } } },
          "402": { "$ref": "#/components/responses/PaymentRequired" }
        }
      }
    },
    "/launch/{mint}": {
      "get": {
        "operationId": "launch_record",
        "summary": "This launch, historically",
        "description": "The deployer's record (launches, graduations, best run, gaps), the bundle at creation, the supply insiders hold, how far along the curve it is; then the launches that looked the same at the same age, graduated or dead, and how they went over the next day, as a spread. Mints minutes old answer from the live recorder. $0.005 a call.",
        "x-price-usd": 0.005,
        "parameters": [{ "name": "mint", "in": "path", "required": true, "schema": { "type": "string" }, "description": "the token's mint address, base58" }],
        "responses": {
          "200": { "description": "the launch and its matches", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LaunchRecord" } } } },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "404": { "description": "no such mint in the warehouse" }
        }
      }
    },
    "/baserate": {
      "get": {
        "operationId": "base_rate",
        "summary": "How often it happens anyway",
        "description": "How many coins first traded inside a market-cap band in a window, how many of those then reached 2x, 5x, 10x and 20x within 3 h, and the median peak. A crossing is a coin's first trade with a market cap inside the band (a coin that jumps over the band in one trade has none); the peak is the highest market cap, curve or pool, in the 3 h after it; USD is at the SOL price of the trade's hour. The check to run before believing a winners-only screenshot, or your own agent. $0.005 a call.",
        "x-price-usd": 0.005,
        "parameters": [
          { "name": "band", "in": "query", "required": true, "schema": { "type": "string", "pattern": "^[0-9]+k-[0-9]+k$", "examples": ["15k-28k"] }, "description": "market cap band in USD; each edge snaps to the nearest of 5k, 10k, 15k, 20k, 28k, 40k, 60k, 100k, 250k, 1000k, and the answer says the band it used" },
          { "name": "from", "in": "query", "required": true, "schema": { "type": "string", "format": "date-time" } },
          { "name": "to", "in": "query", "required": true, "schema": { "type": "string", "format": "date-time" }, "description": "crossings up to here count; each needs its 3 h after, so a window ending under 3 h ago is cut at now minus 3 h" },
          { "name": "venue", "in": "query", "schema": { "type": "string", "enum": ["curve", "pool", "any"], "default": "any" } }
        ],
        "responses": {
          "200": { "description": "the crossings and what became of them", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BaseRate" } } } },
          "402": { "$ref": "#/components/responses/PaymentRequired" }
        }
      }
    },
    "/replay": {
      "post": {
        "operationId": "replay",
        "summary": "Your picks, replayed honestly",
        "description": "Picks with timestamps and sizes in; what they made, pick by pick and in sum, every coin in the window counted including the dead ones, filled on the bonding curve or at the pool as it stood after your latency, with every fee, the fixed costs and the bankroll you set. The most recent eight weeks come back apart from the rest, once per rule to each payer; a changed rule reads them again, so the result counts this payer's reads. A run is a queued job: 202 with an id, then GET /replay/{id}. $2 a run; a run that fails is rerun free on the same id.",
        "x-price-usd": 2,
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["picks"],
          "properties": {
            "picks": { "type": "array", "minItems": 1, "maxItems": 10000, "items": { "type": "object", "required": ["mint", "at", "size_sol"], "properties": {
              "mint": { "type": "string" }, "at": { "type": "string", "format": "date-time", "description": "when your rule decided" }, "size_sol": { "type": "number", "exclusiveMinimum": 0 }
            } } },
            "latency_s": { "type": "number", "default": 3, "description": "seconds from the decision to the fill" },
            "bankroll_sol": { "type": "number", "description": "SOL at risk at once; a pick with no room is skipped" },
            "exit": { "type": "object", "description": "take (x the entry), trail (share off the high), hold (seconds); any combination", "properties": {
              "take": { "type": "number" }, "trail": { "type": "number" }, "hold_s": { "type": "integer" }
            } }
          }
        } } } },
        "responses": {
          "202": { "description": "queued", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReplayJob" } } } },
          "402": { "$ref": "#/components/responses/PaymentRequired" }
        }
      }
    },
    "/replay/{id}": {
      "get": {
        "operationId": "replay_result",
        "summary": "A replay's result",
        "description": "The job's state, and its result once done. Free; the id is the receipt.",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "the job, with the replay once done and the execution model it charged", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReplayJob" } } } },
          "404": { "description": "no such job" }
        }
      }
    }
  },
  "components": {
    "responses": {
      "PaymentRequired": { "description": "x402: the price and where to pay, in the headers; pay and retry the same request" }
    },
    "schemas": {
      "WalletRecord": {
        "type": "object",
        "properties": {
          "class": { "type": "string", "enum": ["winner", "bot", "supply_seller", "leader", "new"], "description": "by rule: winner took out more than it put in over 20+ coin-weeks; bot trades a coin 20+ times a week or 500+ coins; supply_seller took out 1.5x what it put in, 100 SOL or more; leader is a wallet whose buys other wallets follow; new has no record before the mint given, or before today without one" },
          "pnl_sol": { "type": "number" }, "put_in": { "type": "number", "description": "SOL" }, "took_out": { "type": "number", "description": "SOL" },
          "coins": { "type": "integer" }, "first_seen": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "LaunchRecord": {
        "type": "object",
        "properties": {
          "mint": { "type": "string" }, "created": { "type": "string", "format": "date-time" },
          "deployer": { "type": "object", "properties": { "address": { "type": "string" }, "launches": { "type": "integer" }, "graduations": { "type": "integer" }, "best_peak": { "type": "number", "nullable": true }, "last_launch_gap_s": { "type": "integer", "nullable": true }, "launches_last_day": { "type": "integer" } } },
          "bundle_at_creation": { "type": "object", "properties": { "buyers_first_10s": { "type": "integer" }, "supply_share": { "type": "number" } } },
          "insider_supply_share": { "type": "number" },
          "age_s": { "type": "integer", "description": "seconds since creation, at the moment of the call" },
          "curve_progress": { "type": "number", "description": "share of the curve sold, 0 to 1; 1 once migrated" },
          "migrated_at": { "type": "string", "format": "date-time", "nullable": true },
          "matches": { "type": "object", "description": "launches that matched at the same age on the deployer's record, the bundle, the insider share and the curve progress, graduated or not, and how they went from that age", "properties": {
            "n": { "type": "integer" },
            "graduated_share": { "type": "number", "description": "share of the matches that reached the pool" },
            "peak_day1": { "type": "object", "description": "quantiles of the peak over the next 24 h, as a multiple of the market cap at the matching age; the dead count", "additionalProperties": { "type": "number" } },
            "close_day1": { "type": "object", "description": "quantiles of the market cap 24 h on, as the same multiple; a dead coin is near 0", "additionalProperties": { "type": "number" } }
          } }
        }
      },
      "BaseRate": {
        "type": "object",
        "properties": {
          "band": { "type": "string" }, "from": { "type": "string" }, "to": { "type": "string" },
          "crossed": { "type": "integer" }, "per_day": { "type": "number" },
          "reached": { "type": "object", "description": "share of the crossings whose peak within 3 h reached each multiple", "properties": { "2x": { "type": "number" }, "5x": { "type": "number" }, "10x": { "type": "number" }, "20x": { "type": "number" } } },
          "median_peak": { "type": "number" }, "peak_within_s": { "type": "integer", "const": 10800 }
        },
        "example": { "band": "15k-28k", "from": "2026-10-15T07:58:00Z", "to": "2026-10-15T19:12:00Z", "crossed": 852, "per_day": 1822, "reached": { "2x": 0.309, "5x": 0.108, "10x": 0.048, "20x": 0.013 }, "median_peak": 1.42, "peak_within_s": 10800 }
      },
      "ReplayJob": {
        "type": "object",
        "properties": {
          "id": { "type": "string" }, "state": { "type": "string", "enum": ["queued", "running", "done", "failed"] }, "position": { "type": "integer", "nullable": true },
          "result": { "$ref": "#/components/schemas/Replay" }, "error": { "type": "string", "nullable": true }
        }
      },
      "Replay": {
        "type": "object",
        "properties": {
          "sum_sol": { "type": "number" }, "picks": { "type": "integer" }, "filled": { "type": "integer" }, "skipped_no_room": { "type": "integer" }, "skipped_not_covered": { "type": "integer", "description": "picks the replay cannot fill yet: on the bonding curve until curve replays open, or outside the archive" },
          "by_pick": { "type": "array", "items": { "type": "object", "properties": { "mint": { "type": "string" }, "at": { "type": "string" }, "fill_price": { "type": "number", "nullable": true }, "fill_rate": { "type": "number" }, "exit_at": { "type": "string", "nullable": true }, "return": { "type": "number", "description": "net of fees, the fixed costs and the tip lost on a failed try" } } } },
          "by_week": { "type": "object", "additionalProperties": { "type": "number" } },
          "held_out_weeks": { "type": "array", "items": { "type": "string" }, "description": "the most recent eight weeks, returned once per rule signature to each payer; later reads of the same signature get them withheld" },
          "held_out_reads": { "type": "integer", "description": "how many runs this payer has read the held-out weeks in, this one included; more than one is tuning" },
          "execution_model": { "type": "object", "description": "what was charged: fill latency, fee a side, fixed lamports a trade, fill rate by the minute, bankroll, exits" }
        }
      }
    }
  }
}
