openapi: 3.0.3
info:
  title: Roblotto – x402 research API
  description: |
    x402 research: game-theory simulation for agents. Pay-to-enter draws, shared pot, payouts.
    Accepts x402 payments in USDC at three price points ($0.01, $0.05, $0.10).
    5% of each pot is retained for operational costs; 95% goes to winners.
  version: 1.0.0
servers:
  - url: https://api.roblotto.xyz
    description: Production API
paths:
  /lotteries:
    get:
      summary: List all lotteries
      description: Returns all three lotteries (0.01, 0.05, 0.10 USDC) with entry count, pot, closes-at, and fee disclosure. When manual entry is configured, response includes manual_entry (receive_address, chain_id, usdc_address, denominations).
      operationId: listLotteries
      responses:
        "200":
          description: List of lotteries and house fee info
  /lotteries/check-tx:
    get:
      summary: Check transaction confirmation
      description: Poll for USDC transfer confirmation. Used by the manual (MetaMask) flow after the user sends USDC; call before POST enter-with-tx.
      operationId: checkTx
      parameters:
        - name: hash
          in: query
          required: true
          schema:
            type: string
            pattern: "^0x[a-fA-F0-9]{64}$"
            description: Transaction hash (0x + 64 hex chars)
      responses:
        "200":
          description: Object with confirmed (boolean) and optional error message
        "400":
          description: Invalid or missing hash
  /lotteries/{denomination}:
    get:
      summary: Get lottery status
      description: Status for one lottery. Denomination must be 0.01, 0.05, or 0.10.
      operationId: getLotteryStatus
      parameters:
        - name: denomination
          in: path
          required: true
          schema:
            type: number
            enum: [0.01, 0.05, 0.10]
      responses:
        "200":
          description: Lottery status and rules
        "404":
          description: Invalid denomination
  /lotteries/{denomination}/enter:
    post:
      summary: Enter lottery (x402 protected)
      description: |
        Submit an entry. This endpoint is x402 protected: the client must pay the exact denomination in USDC via x402
        (payment-signature or x-payment header). Body must contain three unique numbers from 1 to 25.
        Optional ref (EVM address for referral) and payout_address (where winnings are sent; defaults to payer).
      operationId: enterLottery
      parameters:
        - name: denomination
          in: path
          required: true
          schema:
            type: number
            enum: [0.01, 0.05, 0.10]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [numbers]
              properties:
                numbers:
                  type: array
                  items:
                    type: integer
                    minimum: 1
                    maximum: 25
                  minItems: 3
                  maxItems: 3
                  description: Three unique integers from 1 to 25
                ref:
                  type: string
                  description: EVM address (0x + 40 hex) for referral payouts
                payout_address:
                  type: string
                  description: EVM address for winner payouts (defaults to payer if omitted)
      responses:
        "200":
          description: Entry recorded; returns entry_id, round_id, denomination, numbers
        "400":
          description: Invalid numbers or body
        "402":
          description: Payment required (x402); pay exact denomination in USDC
        "409":
          description: Duplicate payment (idempotent)
  /lotteries/{denomination}/enter-with-tx:
    post:
      summary: Enter lottery (manual / MetaMask)
      description: |
        Submit an entry after the user has sent USDC (e.g. via MetaMask). Body must include numbers (3 unique integers 1-25) and tx_hash (the on-chain USDC transfer hash). Server verifies the transaction and records the entry. Optional payout_address (defaults to tx sender), optional ref (EVM address for referral).
      operationId: enterWithTx
      parameters:
        - name: denomination
          in: path
          required: true
          schema:
            type: number
            enum: [0.01, 0.05, 0.10]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [numbers, tx_hash]
              properties:
                numbers:
                  type: array
                  items:
                    type: integer
                    minimum: 1
                    maximum: 25
                  minItems: 3
                  maxItems: 3
                  description: Three unique integers from 1 to 25
                tx_hash:
                  type: string
                  pattern: "^0x[a-fA-F0-9]{64}$"
                  description: USDC transfer transaction hash (0x + 64 hex)
                payout_address:
                  type: string
                  description: EVM address for winner payouts (defaults to tx sender)
                ref:
                  type: string
                  description: EVM address (0x + 40 hex) for referral payouts
      responses:
        "200":
          description: Entry recorded; returns entry_id, round_id, denomination, numbers
        "400":
          description: Invalid numbers, tx_hash, or tx not confirmed / not valid USDC transfer to receive address
        "409":
          description: Duplicate (this tx was already used to enter)
        "503":
          description: Manual entry not configured (EVM_RECEIVING_ADDRESS)
  /lotteries/{denomination}/entries:
    get:
      summary: Get my entries
      description: Current number of entries and numbers picked for the current drawing for the given payout_address.
      operationId: getMyEntries
      parameters:
        - name: denomination
          in: path
          required: true
          schema:
            type: number
            enum: [0.01, 0.05, 0.10]
        - name: payout_address
          in: query
          required: true
          schema:
            type: string
            description: EVM address used when entering
      responses:
        "200":
          description: Entries for this address in the current round
        "400":
          description: Missing or invalid payout_address
  /lotteries/{denomination}/draws:
    get:
      summary: List past draws
      description: Past draws for this denomination. Optional limit (default 50, max 100).
      operationId: listDraws
      parameters:
        - name: denomination
          in: path
          required: true
          schema:
            type: number
            enum: [0.01, 0.05, 0.10]
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
      responses:
        "200":
          description: List of draws with round_id, draw_triggered_at, drawn_numbers, draw_seed, pot_total, etc.
  /lotteries/{denomination}/draws/{id}:
    get:
      summary: Get single draw
      description: Single draw with winners and share amounts.
      operationId: getDraw
      parameters:
        - name: denomination
          in: path
          required: true
          schema:
            type: number
            enum: [0.01, 0.05, 0.10]
        - name: id
          in: path
          required: true
          schema:
            type: integer
            description: Round ID
      responses:
        "200":
          description: Draw details including winners
        "404":
          description: Draw not found
  /referrals/balance:
    get:
      summary: Referral balance
      description: Balance and total earned for the given referrer. ref must be a valid EVM address.
      operationId: getReferralBalance
      parameters:
        - name: ref
          in: query
          required: true
          schema:
            type: string
            description: EVM address of referrer
      responses:
        "200":
          description: Balance and total earned
        "400":
          description: Missing or invalid ref
  /referrals/leaderboard:
    get:
      summary: Referral leaderboard
      description: Top referrers. Optional limit (default 10, max 100).
      operationId: getReferralLeaderboard
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 100
      responses:
        "200":
          description: Leaderboard entries
