{
  "openapi": "3.1.0",
  "info": {
    "title": "Block Lottos API",
    "description": "Public API for Block Lottos — a provably fair weekly lottery on Polygon. Provides live jackpot data, site stats, and a full advertising submission and management system. No API key required. Ad payments are made in POL on Polygon Mainnet.",
    "version": "1.0.0",
    "contact": {
      "name": "Block Lottos Support",
      "email": "support@blocklottos.com",
      "url": "https://blocklottos.com/contact"
    },
    "license": {
      "name": "Public",
      "url": "https://blocklottos.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://blocklottos.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/jackpot.php": {
      "get": {
        "operationId": "getJackpot",
        "summary": "Get current jackpot",
        "description": "Returns the live jackpot amount read directly from the Polygon smart contract. No auth required. Cached for 60 seconds.",
        "tags": ["Lottery"],
        "responses": {
          "200": {
            "description": "Current jackpot amount",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jackpot_pol": { "type": "number", "description": "Jackpot amount in POL", "example": 142.5 },
                    "jackpot_wei": { "type": "string", "description": "Jackpot amount in wei (string to preserve precision)", "example": "142500000000000000000" },
                    "contract": { "type": "string", "description": "Smart contract address", "example": "0x91Cf492bc8a7884162B998B4de0Aa8b11d38d5A6" },
                    "status": { "type": "string", "enum": ["ok", "error"] }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/stats.php": {
      "get": {
        "operationId": "getStats",
        "summary": "Get site stats",
        "description": "Returns live stats from the Polygon smart contract including draw number, jackpot, and next draw timestamp.",
        "tags": ["Lottery"],
        "responses": {
          "200": {
            "description": "Site statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "draw_number": { "type": "integer", "description": "Upcoming draw number", "example": 8 },
                    "jackpot_pol": { "type": "number", "description": "Current jackpot in POL", "example": 142.5 },
                    "next_draw_timestamp": { "type": "integer", "description": "Unix timestamp of next draw (Saturdays 15:00 UTC)", "example": 1745589600 },
                    "status": { "type": "string", "enum": ["ok", "error"] }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/ads/sizes": {
      "get": {
        "operationId": "getAdSizes",
        "summary": "Get available ad sizes and pricing",
        "description": "Returns all available banner sizes with dimensions, pricing for 7/14/30 day durations, submission fee, and any active discounts. Rate limit: 2 requests/min/IP.",
        "tags": ["Advertising"],
        "responses": {
          "200": {
            "description": "Available ad sizes and pricing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sizes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "string", "example": "728x90" },
                          "width": { "type": "integer", "example": 728 },
                          "height": { "type": "integer", "example": 90 },
                          "label": { "type": "string", "example": "Leaderboard Banner" }
                        }
                      }
                    },
                    "pricing": {
                      "type": "object",
                      "properties": {
                        "7d":  { "type": "number", "description": "7-day placement price in POL", "example": 85 },
                        "14d": { "type": "number", "description": "14-day placement price in POL", "example": 140 },
                        "30d": { "type": "number", "description": "30-day placement price in POL", "example": 250 }
                      }
                    },
                    "submit_fee_pol": { "type": "number", "description": "Non-refundable submission fee in POL", "example": 1 },
                    "discount_pct": { "type": "number", "description": "Active discount percentage (0 if none)", "example": 0 },
                    "discount_expires": { "type": "string", "format": "date-time", "description": "When the discount expires (null if none)" },
                    "currency": { "type": "string", "example": "POL", "description": "Polygon native token" },
                    "network": { "type": "string", "example": "Polygon Mainnet" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/ads/submit": {
      "post": {
        "operationId": "submitAd",
        "summary": "Submit an ad (quote-first flow, step 1)",
        "description": "Submit ad details to get a payment quote. Returns a quote_id and an unsigned POL payment transaction. The caller must sign and broadcast the transaction from their Web3 wallet, then call POST /api/ads/submit/pay to finalise. Rate limit: 10 requests/min/IP.",
        "tags": ["Advertising"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["banner_size", "target_url", "duration_days", "wallet_address", "image_url"],
                "properties": {
                  "banner_size": { "type": "string", "description": "Ad size ID from /api/ads/sizes", "example": "728x90" },
                  "target_url": { "type": "string", "format": "uri", "description": "URL the ad should link to", "example": "https://example.com" },
                  "duration_days": { "type": "integer", "enum": [7, 14, 30], "description": "Duration of the ad placement" },
                  "wallet_address": { "type": "string", "description": "Polygon wallet address that will make payment", "example": "0xYourWalletAddress" },
                  "image_url": { "type": "string", "format": "uri", "description": "Publicly accessible URL of the ad image (must match banner_size dimensions)" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote generated — sign and broadcast the transaction, then call /api/ads/submit/pay",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote_id": { "type": "string", "description": "Use this in the /api/ads/submit/pay call", "example": "q_123456" },
                    "total_pol": { "type": "number", "description": "Total POL to send (submit fee + duration price)", "example": 86 },
                    "submit_fee_pol": { "type": "number", "example": 1 },
                    "placement_fee_pol": { "type": "number", "example": 85 },
                    "payment_address": { "type": "string", "description": "Polygon address to send POL to", "example": "0x311A30fC19174f7B38353daAc5e697D0259812c1" },
                    "expires_at": { "type": "string", "format": "date-time", "description": "Quote expiry — pay before this time" }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid input" },
          "429": { "description": "Rate limit exceeded" }
        }
      }
    },
    "/api/ads/submit/pay": {
      "post": {
        "operationId": "confirmAdPayment",
        "summary": "Confirm ad payment (quote-first flow, step 2)",
        "description": "After broadcasting the POL payment transaction, call this endpoint with the quote_id and transaction hash to finalise the submission. The system will verify the transaction on-chain.",
        "tags": ["Advertising"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["quote_id", "tx_hash"],
                "properties": {
                  "quote_id": { "type": "string", "description": "Quote ID from POST /api/ads/submit", "example": "q_123456" },
                  "tx_hash": { "type": "string", "description": "Transaction hash of your POL payment on Polygon Mainnet", "example": "0xabc123..." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Submission confirmed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "submission_id": { "type": "string", "description": "Use this to check status", "example": "ad_42" },
                    "status": { "type": "string", "example": "pending_review" },
                    "message": { "type": "string", "example": "Ad submitted successfully and is pending review." }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid quote_id or tx_hash" },
          "402": { "description": "Payment not verified on-chain" }
        }
      }
    },
    "/api/ads/status/{submission_id}": {
      "get": {
        "operationId": "getAdStatus",
        "summary": "Check ad submission status",
        "description": "Returns the current status of a submitted ad. Rate limit: 2 requests/min/IP.",
        "tags": ["Advertising"],
        "parameters": [
          {
            "name": "submission_id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "Submission ID returned by /api/ads/submit/pay (e.g. ad_42)",
            "example": "ad_42"
          }
        ],
        "responses": {
          "200": {
            "description": "Ad status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "submission_id": { "type": "string" },
                    "status": {
                      "type": "string",
                      "enum": ["pending_review", "approved", "rejected", "active", "expired"],
                      "description": "Current status of the ad"
                    },
                    "banner_size": { "type": "string" },
                    "target_url": { "type": "string" },
                    "submitted_at": { "type": "string", "format": "date-time" },
                    "reviewed_at": { "type": "string", "format": "date-time", "nullable": true },
                    "expires_at": { "type": "string", "format": "date-time", "nullable": true }
                  }
                }
              }
            }
          },
          "404": { "description": "Submission not found" }
        }
      }
    },
    "/api/ads/wallet/{wallet_address}": {
      "get": {
        "operationId": "getAdsByWallet",
        "summary": "Get all ads for a wallet",
        "description": "Returns all ad submissions associated with a Polygon wallet address. Useful for bots to discover their submission IDs and track statuses. Rate limit: 2 requests/min/IP.",
        "tags": ["Advertising"],
        "parameters": [
          {
            "name": "wallet_address",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "Polygon wallet address (0x...)",
            "example": "0xYourWalletAddress"
          }
        ],
        "responses": {
          "200": {
            "description": "List of ads for this wallet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "wallet": { "type": "string" },
                    "ads": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "submission_id": { "type": "string" },
                          "status": { "type": "string" },
                          "banner_size": { "type": "string" },
                          "target_url": { "type": "string" },
                          "submitted_at": { "type": "string", "format": "date-time" },
                          "expires_at": { "type": "string", "format": "date-time", "nullable": true }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid wallet address" }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Lottery",
      "description": "Live lottery data — jackpot and draw stats"
    },
    {
      "name": "Advertising",
      "description": "Display advertising API — submit, manage, and track ads. Payment in POL on Polygon Mainnet."
    }
  ],
  "externalDocs": {
    "description": "Full API documentation",
    "url": "https://blocklottos.com/api-docs"
  }
}
