{
  "openapi": "3.0.3",
  "info": {
    "title": "DOG DATA API",
    "description": "Comprehensive on-chain analytics API for DOG•GO•TO•THE•MOON (Bitcoin Rune 840000:3). Real-time holder data, transactions, UTXO metrics, forensic behavioral analysis, airdrop tracking, multi-exchange pricing (4 CEXes + 6 DEXes), and cross-chain coverage on Stacks and Solana. Designed for AI agents and programmatic access.",
    "version": "1.1.0",
    "contact": {
      "name": "DOG DATA",
      "url": "https://www.dogdata.xyz"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://www.dogdata.xyz/api",
      "description": "Production"
    },
    {
      "url": "http://localhost:3000/api",
      "description": "Local development"
    }
  ],
  "security": [],
  "tags": [
    { "name": "Agent", "description": "AI agent discovery and capabilities" },
    { "name": "Holders", "description": "DOG holder data, rankings, and address-level lookups" },
    { "name": "Address", "description": "Per-address data: balances, transactions, behavioral profile" },
    { "name": "Transactions", "description": "Bitcoin L1 DOG transactions — feeds, search, heatmaps" },
    { "name": "Stats", "description": "Aggregated DOG token statistics" },
    { "name": "Price", "description": "Real-time DOG price from 10 exchanges (4 CEX + 2 BTC-L2 DEX + 4 Solana DEX)" },
    { "name": "Markets", "description": "Aggregated multi-exchange market data" },
    { "name": "Metrics", "description": "On-chain metrics: UTXO distribution, concentration, realized cap, supply profit/loss" },
    { "name": "Forensic", "description": "Behavioral forensic analysis of holder patterns and Diamond Score" },
    { "name": "Airdrop", "description": "Airdrop distribution, retention, and \"lost DOG\" analysis" },
    { "name": "Multichain", "description": "Cross-chain DOG data on Stacks and Solana" },
    { "name": "Stacks", "description": "Stacks-specific DOG metrics with hourly historical snapshots" },
    { "name": "Bitcoin", "description": "Bitcoin network: blocks, hashrate, mempool, fees" },
    { "name": "Whale Alerts", "description": "Large DOG transfers with severity, context, and tweet-ready format" },
    { "name": "Events", "description": "Server-Sent Events for real-time updates" },
    { "name": "System", "description": "Health, status, OpenAPI spec, root index" },
    { "name": "Auth", "description": "API key generation and verification" }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Optional. Add `Authorization: Bearer <api_key>` for higher rate limits (free=100/h, pro=5000/h, enterprise=50000/h). Public tier (no key) = 100/h."
      }
    },
    "parameters": {
      "Page": {
        "name": "page",
        "in": "query",
        "description": "Page number (1-indexed)",
        "required": false,
        "schema": { "type": "integer", "minimum": 1, "default": 1 }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Items per page",
        "required": false,
        "schema": { "type": "integer", "minimum": 1, "default": 50 }
      },
      "ChainFilter": {
        "name": "chain",
        "in": "query",
        "description": "Filter by chain. Omit for all chains.",
        "required": false,
        "schema": { "type": "string", "enum": ["stacks", "solana", "bitcoin"] }
      }
    },
    "schemas": {
      "Pagination": {
        "type": "object",
        "properties": {
          "page": { "type": "integer", "minimum": 1 },
          "limit": { "type": "integer", "minimum": 1 },
          "total": { "type": "integer", "minimum": 0 },
          "total_pages": { "type": "integer", "minimum": 0 },
          "has_more": { "type": "boolean" }
        },
        "required": ["page", "limit", "total", "total_pages", "has_more"]
      },
      "PaginatedEnvelope": {
        "type": "object",
        "description": "Canonical pagination envelope. Specific endpoints add legacy fields alongside `data` for backwards compatibility.",
        "properties": {
          "data": { "type": "array", "items": {} },
          "pagination": { "$ref": "#/components/schemas/Pagination" },
          "last_updated": { "type": "string", "format": "date-time", "nullable": true }
        },
        "required": ["data", "pagination"]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        },
        "required": ["error"]
      },
      "NormalizedPrice": {
        "type": "object",
        "description": "Canonical price response across all exchanges. Legacy fields (e.g. `change24h`, `lastPrice`, `priceSats`) are also emitted alongside for backwards compatibility.",
        "properties": {
          "exchange": { "type": "string", "example": "kraken" },
          "type": { "type": "string", "enum": ["cex", "dex", "aggregator"] },
          "chain": { "type": "string", "enum": ["bitcoin-l1", "stacks", "solana"], "nullable": true },
          "pair": { "type": "string", "example": "DOG/USD" },
          "price_usd": { "type": "number", "nullable": true },
          "price_btc": { "type": "number", "nullable": true },
          "price_sats": { "type": "number", "nullable": true },
          "change_24h_pct": { "type": "number", "nullable": true },
          "volume_24h_usd": { "type": "number", "nullable": true },
          "high_24h": { "type": "number", "nullable": true },
          "low_24h": { "type": "number", "nullable": true },
          "liquidity_usd": { "type": "number", "nullable": true },
          "fetched_at": { "type": "string", "format": "date-time" },
          "cached": { "type": "boolean" },
          "stale": { "type": "boolean" }
        }
      },
      "Holder": {
        "type": "object",
        "properties": {
          "rank": { "type": "integer" },
          "address": { "type": "string" },
          "total_dog": { "type": "number" },
          "total_amount": { "type": "number", "description": "Same as total_dog (legacy alias)" },
          "utxo_count": { "type": "integer" }
        }
      },
      "ForensicProfile": {
        "type": "object",
        "properties": {
          "address": { "type": "string" },
          "airdrop_rank": { "type": "integer", "nullable": true },
          "airdrop_amount": { "type": "number" },
          "current_rank": { "type": "integer", "nullable": true },
          "current_balance": { "type": "number", "nullable": true },
          "rank_change": { "type": "integer", "nullable": true },
          "rank_status": { "type": "string", "enum": ["in_ranking", "out_of_ranking", "never_ranked"], "nullable": true },
          "retention_rate": { "type": "number", "nullable": true },
          "diamond_score": { "type": "number", "nullable": true },
          "behavior_pattern": { "type": "string", "nullable": true },
          "behavior_category": { "type": "string", "nullable": true },
          "behavior_detail": { "type": "string", "nullable": true },
          "insights": { "type": "array", "items": { "type": "string" } },
          "is_dumping": { "type": "boolean", "nullable": true },
          "first_receive_block": { "type": "integer", "nullable": true },
          "first_receive_time": { "type": "string", "nullable": true }
        }
      },
      "ForensicSummary": {
        "type": "object",
        "properties": {
          "statistics": {
            "type": "object",
            "properties": {
              "total_analyzed": { "type": "integer" },
              "still_holding": { "type": "integer" },
              "sold_everything": { "type": "integer" },
              "accumulated": { "type": "integer" },
              "dumping": { "type": "integer" },
              "diamond_hands": { "type": "integer" },
              "retention_rate": { "type": "number" },
              "by_pattern": {
                "type": "object",
                "additionalProperties": { "type": "integer" }
              }
            }
          },
          "timestamp": { "type": "string", "format": "date-time", "nullable": true },
          "staleness_hours": { "type": "integer", "nullable": true },
          "field_definitions": {
            "type": "object",
            "additionalProperties": { "type": "string" }
          }
        }
      },
      "Capabilities": {
        "type": "object",
        "properties": {
          "service": { "type": "string", "example": "DOG DATA" },
          "version": { "type": "string" },
          "description": { "type": "string" },
          "protocols": { "type": "object" },
          "datasets": { "type": "object" },
          "data_quality": { "type": "object" },
          "rate_limits": { "type": "object" },
          "links": { "type": "object" }
        }
      }
    }
  },
  "paths": {
    "/": {
      "get": {
        "tags": ["System"],
        "summary": "API root index",
        "description": "Lightweight index of high-level endpoints and version info.",
        "responses": {
          "200": {
            "description": "Root listing",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": ["System"],
        "summary": "Health check",
        "responses": {
          "200": { "description": "Service healthy", "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string" }, "timestamp": { "type": "string", "format": "date-time" } } } } } }
        }
      }
    },
    "/status": {
      "get": {
        "tags": ["System"],
        "summary": "Public status snapshot",
        "description": "Aggregated component status with 30/90-day uptime; powers the public /status page.",
        "responses": { "200": { "description": "Status payload", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/status/full": {
      "get": {
        "tags": ["System"],
        "summary": "Detailed status",
        "description": "Full per-component breakdown of crons, infra, external APIs and data sources.",
        "responses": { "200": { "description": "Detailed status payload", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": ["System"],
        "summary": "OpenAPI 3.0 specification",
        "responses": { "200": { "description": "OpenAPI document", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/agent/capabilities": {
      "get": {
        "tags": ["Agent"],
        "summary": "Agent-discoverable capabilities manifest",
        "description": "Single endpoint describing every dataset, protocol (REST, MCP, SSE), rate limits and data sources. Recommended starting point for AI agents.",
        "responses": {
          "200": {
            "description": "Capabilities manifest",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Capabilities" } } }
          }
        }
      }
    },
    "/dog-rune/stats": {
      "get": {
        "tags": ["Stats"],
        "summary": "Aggregated DOG token statistics",
        "description": "Top-level token stats: total holders, supply, distribution, last-scan timestamp.",
        "responses": { "200": { "description": "Stats payload", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/dog-rune/holders": {
      "get": {
        "tags": ["Holders"],
        "summary": "Paginated DOG holder list",
        "description": "Returns ranked holders. Supports paged retrieval, address lookup, and an internal `snapshot=refresh` mode used by the hourly cron.",
        "parameters": [
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/Limit" },
          { "name": "address", "in": "query", "schema": { "type": "string" }, "description": "Lookup a specific address (returns rank and balance)" },
          { "name": "snapshot", "in": "query", "schema": { "type": "string", "enum": ["refresh"] }, "description": "Internal: trigger a fresh snapshot persist (called by cron)" }
        ],
        "responses": {
          "200": {
            "description": "Paginated holder list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/PaginatedEnvelope" },
                    { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Holder" } }, "metadata": { "type": "object" } } }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/dog-rune/transactions-kv": {
      "get": {
        "tags": ["Transactions"],
        "summary": "Recent DOG transactions (KV-backed feed)",
        "description": "Real-time transaction feed (~30s freshness) populated by the indexer cron. Use `?summary=true` for a metadata-only view.",
        "parameters": [
          { "name": "summary", "in": "query", "schema": { "type": "string" }, "description": "If set, returns summary metadata only" }
        ],
        "responses": { "200": { "description": "Transaction feed", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/dog-rune/transactions-unisat": {
      "get": {
        "tags": ["Transactions"],
        "summary": "Recent DOG transactions via Unisat fallback",
        "parameters": [
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "default": 20 } }
        ],
        "responses": { "200": { "description": "Transaction list" } }
      }
    },
    "/dog-rune/heatmap": {
      "get": {
        "tags": ["Transactions"],
        "summary": "Transaction heatmap by hour",
        "parameters": [
          { "name": "timeframe", "in": "query", "schema": { "type": "string", "enum": ["24h", "7d", "30d"], "default": "7d" } },
          { "name": "drill", "in": "query", "schema": { "type": "integer" }, "description": "Drill into a specific bucket index" }
        ],
        "responses": { "200": { "description": "Heatmap grid", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/dog-rune/events-count": {
      "get": {
        "tags": ["Transactions"],
        "summary": "Total indexed event count",
        "responses": { "200": { "description": "Event count", "content": { "application/json": { "schema": { "type": "object", "properties": { "total": { "type": "integer" } } } } } } }
      }
    },
    "/dog-rune/search-tx": {
      "get": {
        "tags": ["Transactions"],
        "summary": "Search a single DOG transaction by txid",
        "parameters": [
          { "name": "txid", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Transaction details" },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/tx/bitcoin/{txid}": {
      "get": {
        "tags": ["Transactions"],
        "summary": "Bitcoin L1 transaction details by txid",
        "parameters": [
          { "name": "txid", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Transaction with senders, receivers, fee, block height" },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/address/bitcoin/{address}": {
      "get": {
        "tags": ["Address"],
        "summary": "Address profile (Bitcoin L1)",
        "description": "Holder profile with balance, rank, UTXO count, forensic profile (if available), and recent transactions. Use `limit`/`offset`/`direction` to paginate transactions.",
        "parameters": [
          { "name": "address", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 50 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } },
          { "name": "direction", "in": "query", "schema": { "type": "string", "enum": ["in", "out"] } }
        ],
        "responses": { "200": { "description": "Address profile" } }
      }
    },
    "/address/{address}/transactions": {
      "get": {
        "tags": ["Address"],
        "summary": "Paginated transaction history for an address",
        "description": "Convenience endpoint that proxies to /address/bitcoin/{address} and returns the canonical pagination envelope.",
        "parameters": [
          { "name": "address", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 50 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } },
          { "name": "direction", "in": "query", "schema": { "type": "string", "enum": ["in", "out"] } }
        ],
        "responses": { "200": { "description": "Paginated transaction list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedEnvelope" } } } } }
      }
    },
    "/forensic/summary": {
      "get": {
        "tags": ["Forensic"],
        "summary": "Forensic behavioral summary (canonical retention metrics)",
        "description": "Canonical source for `still_holding`, `sold_everything`, `retention_rate`, `accumulated`. Includes `staleness_hours` and `field_definitions` for each metric.",
        "responses": {
          "200": {
            "description": "Forensic summary",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ForensicSummary" } } }
          }
        }
      }
    },
    "/forensic/profiles": {
      "get": {
        "tags": ["Forensic"],
        "summary": "Paginated forensic profiles",
        "description": "Returns 75k+ airdrop-recipient profiles with Diamond Score, behavioral pattern, retention. Sorted by receive_count desc, then airdrop_amount desc.",
        "parameters": [
          { "$ref": "#/components/parameters/Page" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 } },
          { "name": "pattern", "in": "query", "schema": { "type": "string" }, "description": "Filter by behavior pattern (e.g. paper_hands, dog_legend, ordinal_believer). Use 'all' or omit for everyone." }
        ],
        "responses": {
          "200": {
            "description": "Paginated profiles",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/PaginatedEnvelope" },
                    { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ForensicProfile" } } } }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/forensic/profile": {
      "get": {
        "tags": ["Forensic"],
        "summary": "Forensic profile lookup by address",
        "parameters": [
          { "name": "address", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Profile", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ForensicProfile" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/airdrop/summary": {
      "get": {
        "tags": ["Airdrop"],
        "summary": "Airdrop summary (retention metrics from forensic source of truth)",
        "description": "Combines distribution figures from airdrop_analytics with canonical retention metrics from /forensic/summary. Includes `accumulator_breakdown`, `last_updated`, `staleness_hours`.",
        "responses": { "200": { "description": "Airdrop summary", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/airdrop/recipients": {
      "get": {
        "tags": ["Airdrop"],
        "summary": "Airdrop recipients list",
        "description": "Returns airdrop recipients with amount, status, and rank. Without pagination params returns the full list (legacy mode); with `page` or `limit` returns the canonical pagination envelope.",
        "parameters": [
          { "$ref": "#/components/parameters/Page" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100 } }
        ],
        "responses": { "200": { "description": "Recipient list", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/airdrop/lost": {
      "get": {
        "tags": ["Airdrop"],
        "summary": "Lost DOG aggregate analysis",
        "description": "Diamond-paws lost DOG estimate — wallets that received airdrop and never sent (presumed lost or extreme HODL). See also `/airdrop/lost/wallets` for the per-wallet list.",
        "responses": { "200": { "description": "Lost analysis summary", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/airdrop/lost/wallets": {
      "get": {
        "tags": ["Airdrop"],
        "summary": "Lost-DOG wallets (paginated)",
        "parameters": [
          { "$ref": "#/components/parameters/Page" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 } },
          { "name": "addr_type", "in": "query", "schema": { "type": "string" }, "description": "Optional address-type filter (e.g. taproot, segwit)" }
        ],
        "responses": { "200": { "description": "Paginated wallets" } }
      }
    },
    "/price/kraken": {
      "get": {
        "tags": ["Price"],
        "summary": "DOG price — Kraken (CEX, DOG/USD)",
        "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } }
      }
    },
    "/price/gateio": {
      "get": { "tags": ["Price"], "summary": "DOG price — Gate.io (CEX, DOG/USDT)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/mexc": {
      "get": { "tags": ["Price"], "summary": "DOG price — MEXC (CEX, DOG/USDT)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/bitget": {
      "get": { "tags": ["Price"], "summary": "DOG price — Bitget (CEX, DOG/USDT)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/bitflow": {
      "get": { "tags": ["Price"], "summary": "DOG price — Bitflow (Stacks AMM, DOG/sBTC)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/dogswap": {
      "get": { "tags": ["Price"], "summary": "DOG price — Dogswap (Bitcoin L1 AMM, DOG/BTC)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/orca": {
      "get": { "tags": ["Price"], "summary": "DOG price — Orca (Solana DEX, DOG/SOL)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/raydium": {
      "get": { "tags": ["Price"], "summary": "DOG price — Raydium (Solana DEX, DOG/USDC)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/meteora": {
      "get": { "tags": ["Price"], "summary": "DOG price — Meteora (Solana DEX, DOG/SOL)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/price/jupiter": {
      "get": { "tags": ["Price"], "summary": "DOG price — Jupiter (Solana aggregator, DOG/USD)", "responses": { "200": { "description": "Normalized price", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NormalizedPrice" } } } } } }
    },
    "/markets": {
      "get": {
        "tags": ["Markets"],
        "summary": "Aggregated multi-exchange market data",
        "responses": { "200": { "description": "Aggregated market payload", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/metrics/utxo": {
      "get": { "tags": ["Metrics"], "summary": "UTXO distribution snapshot", "responses": { "200": { "description": "UTXO buckets and supply per bucket" } } }
    },
    "/metrics/utxo-age": {
      "get": { "tags": ["Metrics"], "summary": "UTXO age stats (LTH/STH split, MVRV, realized cap)", "responses": { "200": { "description": "Age-cohort metrics" } } }
    },
    "/metrics/utxo-count-history": {
      "get": {
        "tags": ["Metrics"],
        "summary": "Time-series of total UTXO count",
        "parameters": [{ "name": "range", "in": "query", "schema": { "type": "string", "default": "30d" } }],
        "responses": { "200": { "description": "Time-series" } }
      }
    },
    "/metrics/holder-concentration": {
      "get": { "tags": ["Metrics"], "summary": "Holder concentration (top 10 / 25 / 50 / 100 percentages)", "responses": { "200": { "description": "Concentration breakdown" } } }
    },
    "/metrics/realized-cap": {
      "get": { "tags": ["Metrics"], "summary": "Realized capitalization", "responses": { "200": { "description": "Realized cap, market cap, MVRV ratio" } } }
    },
    "/metrics/supply-profit-loss": {
      "get": { "tags": ["Metrics"], "summary": "Supply in profit vs loss", "responses": { "200": { "description": "Profit/loss breakdown" } } }
    },
    "/metrics/tx-breakdown": {
      "get": {
        "tags": ["Metrics"],
        "summary": "Transaction breakdown by type",
        "parameters": [{ "name": "range", "in": "query", "schema": { "type": "string", "default": "30d" } }],
        "responses": { "200": { "description": "Tx-type breakdown over range" } }
      }
    },
    "/metrics/history": {
      "get": {
        "tags": ["Metrics"],
        "summary": "Historical aggregated metrics",
        "parameters": [
          { "name": "range", "in": "query", "schema": { "type": "string", "default": "30d" } },
          { "name": "metrics", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated list of metrics to include (e.g. holders,retention,concentration)" }
        ],
        "responses": { "200": { "description": "Time-series payload" } }
      }
    },
    "/multichain/holders": {
      "get": {
        "tags": ["Multichain"],
        "summary": "Cross-chain holders (Stacks via Tenero, Solana via Helius)",
        "parameters": [
          { "$ref": "#/components/parameters/ChainFilter" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } }
        ],
        "responses": { "200": { "description": "Per-chain holder list" } }
      }
    },
    "/multichain/transactions": {
      "get": {
        "tags": ["Multichain"],
        "summary": "Cross-chain recent transactions",
        "parameters": [
          { "$ref": "#/components/parameters/ChainFilter" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 30 } }
        ],
        "responses": { "200": { "description": "Per-chain transactions" } }
      }
    },
    "/multichain/stats": {
      "get": {
        "tags": ["Multichain"],
        "summary": "Cross-chain aggregated stats",
        "description": "Aggregated stats across Stacks and Solana. `last_updated` at top level is the *oldest* per-chain timestamp (worst-case freshness).",
        "responses": { "200": { "description": "Aggregated stats" } }
      }
    },
    "/stacks/history": {
      "get": {
        "tags": ["Stacks"],
        "summary": "Stacks DOG metrics — hourly historical snapshots",
        "description": "Persisted to Supabase. Use `latest=true` for the freshest snapshot only.",
        "parameters": [
          { "name": "days", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 365, "default": 30 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 5000, "default": 720 } },
          { "name": "latest", "in": "query", "schema": { "type": "string", "enum": ["true", "false"] } }
        ],
        "responses": { "200": { "description": "History rows" } }
      }
    },
    "/stacks/snapshot": {
      "get": {
        "tags": ["Stacks"],
        "summary": "Take a Stacks snapshot (cron-protected)",
        "description": "Triggers a fresh hourly snapshot of Stacks DOG metrics into Supabase. Called by Vercel Cron.",
        "responses": { "200": { "description": "Snapshot persisted" } }
      },
      "post": {
        "tags": ["Stacks"],
        "summary": "Take a Stacks snapshot (POST variant)",
        "responses": { "200": { "description": "Snapshot persisted" } }
      }
    },
    "/bitcoin": {
      "get": {
        "tags": ["Bitcoin"],
        "summary": "Bitcoin network status",
        "description": "Live block height, hashrate, mempool, and fee tiers from the local full node.",
        "responses": { "200": { "description": "Network status" } }
      }
    },
    "/whale-alerts": {
      "get": {
        "tags": ["Whale Alerts"],
        "summary": "Recent large DOG transfers",
        "parameters": [
          { "name": "threshold", "in": "query", "schema": { "type": "integer", "default": 1000000 }, "description": "Min DOG amount to qualify as a whale alert" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 } },
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["full", "tweet", "compact"], "default": "full" } },
          { "name": "chain", "in": "query", "schema": { "type": "string", "enum": ["bitcoin", "stacks", "solana"] } }
        ],
        "responses": { "200": { "description": "Whale alerts list" } }
      }
    },
    "/events": {
      "get": {
        "tags": ["Events"],
        "summary": "Server-Sent Events stream",
        "description": "SSE feed for `new_transaction`, `price_update`, `whale_alert`, `new_block`. Filter by `events=` (comma-separated). Use `whale_threshold` to tune whale alerts.",
        "parameters": [
          { "name": "events", "in": "query", "schema": { "type": "string" }, "description": "Comma-separated event names" },
          { "name": "whale_threshold", "in": "query", "schema": { "type": "integer", "default": 1000000 } }
        ],
        "responses": {
          "200": {
            "description": "SSE stream",
            "content": { "text/event-stream": { "schema": { "type": "string" } } }
          }
        }
      }
    },
    "/keys/generate": {
      "post": {
        "tags": ["Auth"],
        "summary": "Generate a new API key",
        "description": "Issues an API key tied to a tier. Internal/admin use.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tier": { "type": "string", "enum": ["free", "pro", "enterprise"] },
                  "name": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": { "200": { "description": "API key created" } }
      }
    },
    "/keys/verify": {
      "get": {
        "tags": ["Auth"],
        "summary": "Verify an API key",
        "description": "Checks the API key in the Authorization header and returns its tier.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": { "description": "Key info" },
          "401": { "description": "Invalid or missing key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/update-transactions": {
      "get": {
        "tags": ["System"],
        "summary": "Internal cron: refresh transaction KV cache",
        "description": "Called by Vercel Cron every 3 minutes. Requires the `secret` query param.",
        "parameters": [
          { "name": "secret", "in": "query", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Refresh result" },
          "401": { "description": "Bad secret" }
        }
      }
    },
    "/cron/whale-poster": {
      "get": {
        "tags": ["System"],
        "summary": "Internal cron: post whale alerts",
        "parameters": [
          { "name": "secret", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Posted whale alerts" } }
      }
    }
  }
}
