openapi: 3.1.0
info:
  title: FalsifyLab Alpha REST API
  version: 0.1.7
  summary: REST endpoints behind the FalsifyLab Alpha MCP server. 10 live finance data tools.
  description: |
    Same data surface that powers the MCP server at `mcp.falsifylab.com`. Public REST
    endpoints at `falsifylab.com/api/*` expose 10 finance tools covering DeFi yield,
    Hyperliquid vaults, SEC filings, US macro tape, ETF flows, Polymarket whales,
    onchain Solana wallets, and cross-source confluence detection.

    Auth: Bearer header optional. Without auth = anonymous free tier (24h cache,
    10 results/query, 60 req/hr). Bearer with Whop license key or OAuth JWT = Pro
    tier (real-time, 100 results/query, 90d history).
  contact:
    name: FalsifyLab
    email: ops@falsifylab.com
    url: https://falsifylab.com
  license:
    name: MIT
    identifier: MIT
servers:
  - url: https://falsifylab.com
    description: Production
  - url: https://mcp.falsifylab.com
    description: MCP host (same data, MCP JSON-RPC at /)

security:
  - {}
  - bearerAuth: []

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        Whop license key (Pro tier subscribers) OR signed JWT minted by the
        OAuth 2.1 flow at `mcp.falsifylab.com/authorize`.
  schemas:
    Error:
      type: object
      properties:
        error: { type: string }
        code: { type: integer, nullable: true }
      required: [error]
    GeneratedAt:
      type: string
      format: date-time
      example: "2026-05-14T03:15:04.847112+00:00"

paths:
  /api/yield/top:
    get:
      summary: Top DeFi yield farms (emissions-stripped APY)
      operationId: top_yield_farms
      tags: [DeFi]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
          description: max results. free max=10, pro max=50.
        - name: min_apy
          in: query
          schema: { type: number }
          description: minimum realistic APY %
        - name: chain
          in: query
          schema: { type: string }
          description: filter by chain (e.g. ethereum, arbitrum)
        - name: asset
          in: query
          schema: { type: string }
          description: filter pools containing asset (e.g. ETH, USDC)
      responses:
        "200":
          description: yield farm list
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        protocol: { type: string }
                        chain: { type: string }
                        assets: { type: array, items: { type: string } }
                        tvl_usd: { type: number }
                        base_apy: { type: number }
                        reward_apr: { type: number }
                        realistic_apy: { type: number }
                  generated_at: { $ref: "#/components/schemas/GeneratedAt" }

  /api/hl_vaults:
    get:
      summary: Hyperliquid vault leaderboard
      operationId: hl_vault_leaderboard
      tags: [Crypto, Onchain]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
        - name: sort_by
          in: query
          schema: { type: string, enum: [score, tvl, return_30d, followers], default: score }
      responses:
        "200":
          description: vault list
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  vaults:
                    type: array
                    items:
                      type: object
                      properties:
                        address: { type: string }
                        name: { type: string }
                        nav_usd: { type: number }
                        return_30d_pct: { type: number }
                        max_dd_pct: { type: number }
                        follower_count: { type: integer }
                        composite_score: { type: number }
                        leader: { type: string }
                  generated_at: { $ref: "#/components/schemas/GeneratedAt" }

  /api/form4/clusters:
    get:
      summary: SEC Form 4 insider buy clusters
      operationId: insider_buy_clusters
      tags: [SEC, Equity]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
        - name: min_filers
          in: query
          schema: { type: integer, default: 3 }
          description: minimum filer count per cluster
        - name: buys_only
          in: query
          schema: { type: string, enum: ["0", "1"], default: "0" }
          description: '"1" excludes sell clusters'
      responses:
        "200":
          description: clusters
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        ticker: { type: string }
                        filer_count: { type: integer }
                        is_buy_cluster: { type: boolean }
                        total_usd: { type: number }
                  generated_at: { $ref: "#/components/schemas/GeneratedAt" }

  /api/sec8k/today:
    get:
      summary: Material SEC 8-K filings filtered by item code
      operationId: sec8k_material_today
      tags: [SEC, Equity]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 100 }
        - name: items
          in: query
          schema: { type: string }
          description: comma-separated 8-K item codes e.g. "2.02,5.02"
        - name: ticker
          in: query
          schema: { type: string }
      responses:
        "200":
          description: 8-K list
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        ticker: { type: string }
                        company: { type: string }
                        filed_at: { type: string, format: date-time }
                        items: { type: array, items: { type: string } }
                        url: { type: string }
                  generated_at: { $ref: "#/components/schemas/GeneratedAt" }

  /api/macro:
    get:
      summary: US macro tape (equities, vol, rates, FX, commodities, crypto)
      operationId: macro_tape
      tags: [Macro]
      parameters:
        - name: symbols
          in: query
          schema: { type: string }
          description: comma-separated keys e.g. "BTC,ETH,SPX,VIX"
      responses:
        "200":
          description: macro snapshot
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        key: { type: string }
                        symbol: { type: string }
                        label: { type: string }
                        asset_class: { type: string }
                        last: { type: number }
                        prev_close: { type: number }
                        pct_1d: { type: number }
                        pct_5d: { type: number }

  /api/etf_flow:
    get:
      summary: US spot BTC + ETH ETF flows
      operationId: etf_flow_today
      tags: [Crypto, ETF]
      responses:
        "200":
          description: per-issuer flows
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        asset: { type: string }
                        issuer: { type: string }
                        ticker: { type: string }
                        flow_usd: { type: number }
                        aum_usd: { type: number }

  /api/airdrops:
    get:
      summary: Active airdrop / yield-gap farms
      operationId: active_airdrop_farms
      tags: [DeFi, Airdrops]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
        - name: min_apy
          in: query
          schema: { type: number }
        - name: min_tvl_usd
          in: query
          schema: { type: number }
        - name: chain
          in: query
          schema: { type: string }
      responses:
        "200":
          description: airdrop farms
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  airdrops:
                    type: array
                    items:
                      type: object
                      properties:
                        protocol: { type: string }
                        chain: { type: string }
                        pool: { type: string }
                        realistic_apy: { type: number }
                        tvl_usd: { type: number }
                        capital_required_usd: { type: number }
                        confidence_score: { type: number }

  /api/polymarket/whales:
    get:
      summary: Top Polymarket wallets and their active $10k+ positions
      operationId: polymarket_whale_positions
      tags: [PredictionMarkets]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
      responses:
        "200":
          description: whale positions
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        wallet: { type: string }
                        score: { type: number }
                        active_positions: { type: array, items: { type: object } }

  /api/confluence:
    get:
      summary: Cross-source signal confluence
      operationId: confluence_today
      tags: [Confluence]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
      responses:
        "200":
          description: tickers/assets where 2+ FalsifyLab signals align in 24h
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        asset: { type: string }
                        signal_count: { type: integer }
                        sources: { type: array, items: { type: string } }
                        composite_score: { type: number }

  /api/onchain/wallets:
    get:
      summary: Solana smart-wallet copy-trade leaderboard
      operationId: onchain_smart_wallets
      tags: [Onchain, Crypto]
      parameters:
        - name: limit
          in: query
          schema: { type: integer, default: 5, minimum: 1, maximum: 50 }
      responses:
        "200":
          description: ranked wallets
          content:
            application/json:
              schema:
                type: object
                properties:
                  count: { type: integer }
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        wallet: { type: string }
                        score: { type: number }
                        win_rate: { type: number }
                        avg_trade_size_usd: { type: number }
