{"openapi":"3.1.0","info":{"title":"Megapot Data API","description":"Read API for Megapot rounds and wallet data.\n\n**Use of this API is governed by the [Megapot Data API Terms of Service](https://api.megapot.io/tos).**\n\nVisit your [megapot.io dashboard](https://megapot.io/dashboard) to create an API key. Need help? Reach out at [megapot.io/support](https://megapot.io/support).","version":"1.6.0"},"servers":[{"url":"https://api.megapot.io"}],"components":{"schemas":{"Round":{"type":"object","properties":{"id":{"$ref":"#/definitions/RoundId"},"status":{"$ref":"#/definitions/RoundStatus"},"prize_pool":{"$ref":"#/definitions/Amount"},"ticket_count":{"$ref":"#/definitions/__schema2"},"unique_participants":{"$ref":"#/definitions/__schema2"},"winners_count":{"$ref":"#/definitions/__schema2"},"top_prize_amount":{"$ref":"#/definitions/__schema3"},"top_prize_winners_count":{"$ref":"#/definitions/__schema2"},"lp_earnings":{"$ref":"#/definitions/Amount"},"started_at":{"$ref":"#/definitions/__schema4"},"ended_at":{"$ref":"#/definitions/__schema5"},"settled_at":{"$ref":"#/definitions/__schema6"},"ball_pool":{"$ref":"#/definitions/BallPool"},"winning_numbers":{"$ref":"#/definitions/__schema7"},"prize_tiers":{"$ref":"#/definitions/__schema9"}},"required":["id","status","prize_pool","ticket_count","unique_participants","winners_count","top_prize_amount","top_prize_winners_count","lp_earnings","started_at","ended_at","settled_at","ball_pool","winning_numbers","prize_tiers"],"additionalProperties":false,"description":"A round of the lottery, with per-round aggregates folded in. `started_at` is derived from the previous round's `settled_at` (null for round 1). `ended_at` is the contract's drawing time. `top_prize_amount` is null until the round is drawn with winners. `lp_earnings` is always populated — `{amount: \"0\", …}` while the round is open and accumulates as tickets sell, finalized at settlement. `ball_pool` is always populated; `winning_numbers` is null until the round is drawn; `prize_tiers` is null until per-tier payouts land (post-settlement, after the contract pipeline finishes).","example":{"id":"172","status":"settled","prize_pool":{"amount":"500000000000","decimals":6},"ticket_count":1001,"unique_participants":412,"winners_count":300,"top_prize_amount":{"amount":"183029000000","decimals":6},"top_prize_winners_count":1,"lp_earnings":{"amount":"1234567","decimals":6},"started_at":"2026-04-14T18:00:00.000Z","ended_at":"2026-04-15T18:00:00.000Z","settled_at":"2026-04-15T18:05:32.000Z","ball_pool":{"normals_max":49,"bonusball_max":26},"winning_numbers":{"normals":[3,17,25,38,49],"bonusball":7},"prize_tiers":[{"tier_id":0,"normal_matches":0,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":847},{"tier_id":1,"normal_matches":0,"bonusball_match":true,"payout":{"amount":"500000","decimals":6},"ticket_count":92},{"tier_id":2,"normal_matches":1,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":53},{"tier_id":3,"normal_matches":1,"bonusball_match":true,"payout":{"amount":"1000000","decimals":6},"ticket_count":6},{"tier_id":4,"normal_matches":2,"bonusball_match":false,"payout":{"amount":"2000000","decimals":6},"ticket_count":2},{"tier_id":5,"normal_matches":2,"bonusball_match":true,"payout":{"amount":"5000000","decimals":6},"ticket_count":1},{"tier_id":6,"normal_matches":3,"bonusball_match":false,"payout":{"amount":"10000000","decimals":6},"ticket_count":0},{"tier_id":7,"normal_matches":3,"bonusball_match":true,"payout":{"amount":"25000000","decimals":6},"ticket_count":0},{"tier_id":8,"normal_matches":4,"bonusball_match":false,"payout":{"amount":"50000000","decimals":6},"ticket_count":0},{"tier_id":9,"normal_matches":4,"bonusball_match":true,"payout":{"amount":"100000000","decimals":6},"ticket_count":0},{"tier_id":10,"normal_matches":5,"bonusball_match":false,"payout":{"amount":"250000000000","decimals":6},"ticket_count":0},{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}]},"definitions":{"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"RoundStatus":{"type":"string","enum":["active","settled"],"description":"Round lifecycle state. `active` covers DB `open` (selling tickets) and DB `locked` (drawing in progress). `settled` covers DB `settled` (payouts done)."},"Amount":{"type":"object","properties":{"amount":{"$ref":"#/definitions/__schema0"},"decimals":{"$ref":"#/definitions/__schema1"}},"required":["amount","decimals"],"additionalProperties":false,"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"__schema0":{"type":"string","pattern":"^\\d+$"},"__schema1":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema2":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema3":{"nullable":true,"allOf":[{"$ref":"#/definitions/Amount"}]},"__schema4":{"nullable":true,"allOf":[{"$ref":"#/definitions/Timestamp"}]},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"__schema5":{"nullable":true,"allOf":[{"$ref":"#/definitions/Timestamp"}]},"__schema6":{"nullable":true,"allOf":[{"$ref":"#/definitions/Timestamp"}]},"BallPool":{"type":"object","properties":{"normals_max":{"$ref":"#/definitions/__schema2"},"bonusball_max":{"$ref":"#/definitions/__schema2"}},"required":["normals_max","bonusball_max"],"additionalProperties":false,"description":"Contract-configured ranges for this round's normal balls (1..normals_max) and bonusball (1..bonusball_max). Both values are always populated, including on the active round, since they're set when the round opens.","example":{"normals_max":49,"bonusball_max":26}},"__schema7":{"nullable":true,"allOf":[{"$ref":"#/definitions/WinningNumbers"}]},"WinningNumbers":{"type":"object","properties":{"normals":{"$ref":"#/definitions/__schema8"},"bonusball":{"$ref":"#/definitions/__schema2"}},"required":["normals","bonusball"],"additionalProperties":false,"description":"The 5 normal numbers + 1 bonusball drawn at settlement. Null on the Round resource until the round is drawn.","example":{"normals":[3,17,25,38,49],"bonusball":7}},"__schema8":{"minItems":5,"maxItems":5,"type":"array","items":{"$ref":"#/definitions/__schema2"}},"__schema9":{"nullable":true,"minItems":12,"maxItems":12,"type":"array","items":{"$ref":"#/definitions/PrizeTier"}},"PrizeTier":{"type":"object","properties":{"tier_id":{"$ref":"#/definitions/__schema10"},"normal_matches":{"$ref":"#/definitions/__schema11"},"bonusball_match":{"$ref":"#/definitions/__schema12"},"payout":{"$ref":"#/definitions/Amount"},"ticket_count":{"$ref":"#/definitions/__schema2"}},"required":["tier_id","normal_matches","bonusball_match","payout","ticket_count"],"additionalProperties":false,"description":"One of 12 prize tiers for a settled round. `tier_id = normal_matches * 2 + (bonusball_match ? 1 : 0)`. Tiers 0 and 2 are zero-payout (no bonus at low matches) but receive non-zero `ticket_count` for tickets that landed there. `payout` is the contract's gross per-ticket amount; per-ticket actual winnings (`Ticket.winnings_amount`) net out the round's referral share.","example":{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}},"__schema10":{"type":"integer","minimum":0,"maximum":11},"__schema11":{"type":"integer","minimum":0,"maximum":5},"__schema12":{"type":"boolean"}}},"RoundStatus":{"type":"string","enum":["active","settled"],"description":"Round lifecycle state. `active` covers DB `open` (selling tickets) and DB `locked` (drawing in progress). `settled` covers DB `settled` (payouts done)."},"Ticket":{"type":"object","properties":{"id":{"$ref":"#/definitions/__schema0"},"wallet":{"$ref":"#/definitions/Address"},"buyer":{"$ref":"#/definitions/Address"},"round_id":{"$ref":"#/definitions/RoundId"},"user_ticket_id":{"$ref":"#/definitions/__schema0"},"normals":{"$ref":"#/definitions/__schema1"},"bonusball":{"$ref":"#/definitions/__schema2"},"matched_normals":{"$ref":"#/definitions/__schema3"},"bonusball_match":{"$ref":"#/definitions/__schema4"},"winnings_amount":{"$ref":"#/definitions/__schema5"},"claimed":{"$ref":"#/definitions/__schema8"},"claimed_tx_hash":{"$ref":"#/definitions/__schema9"},"tx_hash":{"$ref":"#/definitions/TxHash"},"block_number":{"$ref":"#/definitions/__schema2"},"created_at":{"$ref":"#/definitions/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","winnings_amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"additionalProperties":false,"description":"A single ticket bought against a round. Fields `matched_normals`, `bonusball_match`, and `winnings_amount` are null until the round is drawn. `wallet` is the recipient (owner); `buyer` is the address that submitted the purchase (may differ for gifted/agent buys).","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"winnings_amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"},"definitions":{"__schema0":{"type":"string","minLength":1,"pattern":"^\\d+$"},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"__schema1":{"minItems":5,"maxItems":5,"type":"array","items":{"$ref":"#/definitions/__schema2"}},"__schema2":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema3":{"nullable":true,"maximum":5,"allOf":[{"$ref":"#/definitions/__schema2"}]},"__schema4":{"nullable":true,"type":"boolean"},"__schema5":{"nullable":true,"allOf":[{"$ref":"#/definitions/Amount"}]},"Amount":{"type":"object","properties":{"amount":{"$ref":"#/definitions/__schema6"},"decimals":{"$ref":"#/definitions/__schema7"}},"required":["amount","decimals"],"additionalProperties":false,"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"__schema6":{"type":"string","pattern":"^\\d+$"},"__schema7":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema8":{"type":"boolean"},"__schema9":{"nullable":true,"allOf":[{"$ref":"#/definitions/TxHash"}]},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"}}},"Win":{"type":"object","properties":{"id":{"$ref":"#/definitions/__schema0"},"wallet":{"$ref":"#/definitions/Address"},"buyer":{"$ref":"#/definitions/Address"},"round_id":{"$ref":"#/definitions/RoundId"},"user_ticket_id":{"$ref":"#/definitions/__schema0"},"normals":{"$ref":"#/definitions/__schema1"},"bonusball":{"$ref":"#/definitions/__schema2"},"matched_normals":{"$ref":"#/definitions/__schema3"},"bonusball_match":{"$ref":"#/definitions/__schema4"},"amount":{"$ref":"#/definitions/Amount"},"claimed":{"$ref":"#/definitions/__schema7"},"claimed_tx_hash":{"$ref":"#/definitions/__schema8"},"tx_hash":{"$ref":"#/definitions/TxHash"},"block_number":{"$ref":"#/definitions/__schema2"},"created_at":{"$ref":"#/definitions/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"additionalProperties":false,"description":"A winning ticket. Same shape as Ticket with `winnings_amount` renamed `amount` and the three round-drawn fields (`amount`, `matched_normals`, `bonusball_match`) guaranteed non-null. `claimed_tx_hash` stays nullable — a Win can be unclaimed.","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"},"definitions":{"__schema0":{"type":"string","minLength":1,"pattern":"^\\d+$"},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"__schema1":{"minItems":5,"maxItems":5,"type":"array","items":{"$ref":"#/definitions/__schema2"}},"__schema2":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema3":{"maximum":5,"allOf":[{"$ref":"#/definitions/__schema2"}]},"__schema4":{"type":"boolean"},"Amount":{"type":"object","properties":{"amount":{"$ref":"#/definitions/__schema5"},"decimals":{"$ref":"#/definitions/__schema6"}},"required":["amount","decimals"],"additionalProperties":false,"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"__schema5":{"type":"string","pattern":"^\\d+$"},"__schema6":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema7":{"type":"boolean"},"__schema8":{"nullable":true,"allOf":[{"$ref":"#/definitions/TxHash"}]},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"}}},"WalletStats":{"type":"object","properties":{"address":{"$ref":"#/definitions/Address"},"total_tickets":{"$ref":"#/definitions/__schema0"},"total_wins":{"$ref":"#/definitions/__schema1"},"total_winnings":{"$ref":"#/definitions/Amount"},"total_spent":{"$ref":"#/definitions/Amount"},"total_referral_earnings":{"$ref":"#/definitions/Amount"},"rounds_played":{"$ref":"#/definitions/__schema4"},"first_seen_at":{"$ref":"#/definitions/__schema5"},"last_seen_at":{"$ref":"#/definitions/__schema6"}},"required":["address","total_tickets","total_wins","total_winnings","total_spent","total_referral_earnings","rounds_played","first_seen_at","last_seen_at"],"additionalProperties":false,"description":"Aggregate ticket, winnings, and referral stats for a wallet. Ticket and winnings figures are recipient-keyed (wallet that owns the tickets, not the buyer). `total_referral_earnings` is lifetime gross income earned by referring other wallets (purchase fees + claim bonuses + still-unclaimed pending winnings). Unknown wallets return zeros with null timestamps.","example":{"address":"0x1111111111111111111111111111111111111111","total_tickets":12,"total_wins":3,"total_winnings":{"amount":"150000000","decimals":6},"total_spent":{"amount":"60000000","decimals":6},"total_referral_earnings":{"amount":"123456","decimals":6},"rounds_played":7,"first_seen_at":"2026-01-15T10:00:00.000Z","last_seen_at":"2026-04-29T12:34:56.000Z"},"definitions":{"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"__schema0":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema1":{"type":"integer","minimum":0,"maximum":9007199254740991},"Amount":{"type":"object","properties":{"amount":{"$ref":"#/definitions/__schema2"},"decimals":{"$ref":"#/definitions/__schema3"}},"required":["amount","decimals"],"additionalProperties":false,"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"__schema2":{"type":"string","pattern":"^\\d+$"},"__schema3":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema4":{"type":"integer","minimum":0,"maximum":9007199254740991},"__schema5":{"nullable":true,"allOf":[{"$ref":"#/definitions/Timestamp"}]},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"__schema6":{"nullable":true,"allOf":[{"$ref":"#/definitions/Timestamp"}]}}},"Amount":{"type":"object","properties":{"amount":{"$ref":"#/definitions/__schema0"},"decimals":{"$ref":"#/definitions/__schema1"}},"required":["amount","decimals"],"additionalProperties":false,"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6},"definitions":{"__schema0":{"type":"string","pattern":"^\\d+$"},"__schema1":{"type":"integer","minimum":0,"maximum":9007199254740991}}},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"},"ErrorEnvelope":{"type":"object","properties":{"error":{"$ref":"#/definitions/__schema0"}},"required":["error"],"additionalProperties":false,"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}},"definitions":{"__schema0":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"],"additionalProperties":false}}}},"securitySchemes":{"bearerApiKey":{"type":"http","scheme":"bearer","description":"Format: `mpk_live_<22 base62 chars>`."}}},"paths":{"/v1/rounds/active":{"get":{"operationId":"getV1RoundsActive","tags":["Round"],"summary":"Current active round","description":"Returns the round currently selling tickets or being drawn (DB `status IN ('open', 'locked')`). Production invariant: always one such round; the 503 response surfaces a data-pipeline anomaly.","responses":{"200":{"description":"The current active round","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/RoundId"},"status":{"$ref":"#/components/schemas/RoundStatus"},"prize_pool":{"$ref":"#/components/schemas/Amount"},"ticket_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"unique_participants":{"type":"integer","minimum":0,"maximum":9007199254740991},"winners_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"top_prize_amount":{"anyOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}]},"top_prize_winners_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"lp_earnings":{"$ref":"#/components/schemas/Amount"},"started_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"ended_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"settled_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"ball_pool":{"$ref":"#/components/schemas/BallPool"},"winning_numbers":{"anyOf":[{"$ref":"#/components/schemas/WinningNumbers"},{"type":"null"}]},"prize_tiers":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"$ref":"#/components/schemas/PrizeTier"}},{"type":"null"}]}},"required":["id","status","prize_pool","ticket_count","unique_participants","winners_count","top_prize_amount","top_prize_winners_count","lp_earnings","started_at","ended_at","settled_at","ball_pool","winning_numbers","prize_tiers"],"description":"A round of the lottery, with per-round aggregates folded in. `started_at` is derived from the previous round's `settled_at` (null for round 1). `ended_at` is the contract's drawing time. `top_prize_amount` is null until the round is drawn with winners. `lp_earnings` is always populated — `{amount: \"0\", …}` while the round is open and accumulates as tickets sell, finalized at settlement. `ball_pool` is always populated; `winning_numbers` is null until the round is drawn; `prize_tiers` is null until per-tier payouts land (post-settlement, after the contract pipeline finishes).","example":{"id":"172","status":"settled","prize_pool":{"amount":"500000000000","decimals":6},"ticket_count":1001,"unique_participants":412,"winners_count":300,"top_prize_amount":{"amount":"183029000000","decimals":6},"top_prize_winners_count":1,"lp_earnings":{"amount":"1234567","decimals":6},"started_at":"2026-04-14T18:00:00.000Z","ended_at":"2026-04-15T18:00:00.000Z","settled_at":"2026-04-15T18:05:32.000Z","ball_pool":{"normals_max":49,"bonusball_max":26},"winning_numbers":{"normals":[3,17,25,38,49],"bonusball":7},"prize_tiers":[{"tier_id":0,"normal_matches":0,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":847},{"tier_id":1,"normal_matches":0,"bonusball_match":true,"payout":{"amount":"500000","decimals":6},"ticket_count":92},{"tier_id":2,"normal_matches":1,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":53},{"tier_id":3,"normal_matches":1,"bonusball_match":true,"payout":{"amount":"1000000","decimals":6},"ticket_count":6},{"tier_id":4,"normal_matches":2,"bonusball_match":false,"payout":{"amount":"2000000","decimals":6},"ticket_count":2},{"tier_id":5,"normal_matches":2,"bonusball_match":true,"payout":{"amount":"5000000","decimals":6},"ticket_count":1},{"tier_id":6,"normal_matches":3,"bonusball_match":false,"payout":{"amount":"10000000","decimals":6},"ticket_count":0},{"tier_id":7,"normal_matches":3,"bonusball_match":true,"payout":{"amount":"25000000","decimals":6},"ticket_count":0},{"tier_id":8,"normal_matches":4,"bonusball_match":false,"payout":{"amount":"50000000","decimals":6},"ticket_count":0},{"tier_id":9,"normal_matches":4,"bonusball_match":true,"payout":{"amount":"100000000","decimals":6},"ticket_count":0},{"tier_id":10,"normal_matches":5,"bonusball_match":false,"payout":{"amount":"250000000000","decimals":6},"ticket_count":0},{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}]},"$defs":{"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"RoundStatus":{"type":"string","enum":["active","settled"],"description":"Round lifecycle state. `active` covers DB `open` (selling tickets) and DB `locked` (drawing in progress). `settled` covers DB `settled` (payouts done)."},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"BallPool":{"type":"object","properties":{"normals_max":{"type":"integer","minimum":0,"maximum":9007199254740991},"bonusball_max":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["normals_max","bonusball_max"],"description":"Contract-configured ranges for this round's normal balls (1..normals_max) and bonusball (1..bonusball_max). Both values are always populated, including on the active round, since they're set when the round opens.","example":{"normals_max":49,"bonusball_max":26}},"WinningNumbers":{"type":"object","properties":{"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["normals","bonusball"],"description":"The 5 normal numbers + 1 bonusball drawn at settlement. Null on the Round resource until the round is drawn.","example":{"normals":[3,17,25,38,49],"bonusball":7}},"PrizeTier":{"type":"object","properties":{"tier_id":{"type":"integer","minimum":0,"maximum":11},"normal_matches":{"type":"integer","minimum":0,"maximum":5},"bonusball_match":{"type":"boolean"},"payout":{"$ref":"#/components/schemas/Amount"},"ticket_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["tier_id","normal_matches","bonusball_match","payout","ticket_count"],"description":"One of 12 prize tiers for a settled round. `tier_id = normal_matches * 2 + (bonusball_match ? 1 : 0)`. Tiers 0 and 2 are zero-payout (no bonus at low matches) but receive non-zero `ticket_count` for tickets that landed there. `payout` is the contract's gross per-ticket amount; per-ticket actual winnings (`Ticket.winnings_amount`) net out the round's referral share.","example":{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"503":{"description":"Upstream dependency unavailable (`error.code = upstream_unavailable`). Retry with backoff.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/rounds":{"get":{"operationId":"getV1Rounds","tags":["Round"],"summary":"List rounds","description":"Paginated list of rounds, newest first (`drawing_id DESC`). Pass `next_cursor` from the previous page back via `?cursor=...` to walk the list. Default `limit` is 50, max 100.","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Paginated rounds","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Round"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Round":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/RoundId"},"status":{"$ref":"#/components/schemas/RoundStatus"},"prize_pool":{"$ref":"#/components/schemas/Amount"},"ticket_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"unique_participants":{"type":"integer","minimum":0,"maximum":9007199254740991},"winners_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"top_prize_amount":{"anyOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}]},"top_prize_winners_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"lp_earnings":{"$ref":"#/components/schemas/Amount"},"started_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"ended_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"settled_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"ball_pool":{"$ref":"#/components/schemas/BallPool"},"winning_numbers":{"anyOf":[{"$ref":"#/components/schemas/WinningNumbers"},{"type":"null"}]},"prize_tiers":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"$ref":"#/components/schemas/PrizeTier"}},{"type":"null"}]}},"required":["id","status","prize_pool","ticket_count","unique_participants","winners_count","top_prize_amount","top_prize_winners_count","lp_earnings","started_at","ended_at","settled_at","ball_pool","winning_numbers","prize_tiers"],"description":"A round of the lottery, with per-round aggregates folded in. `started_at` is derived from the previous round's `settled_at` (null for round 1). `ended_at` is the contract's drawing time. `top_prize_amount` is null until the round is drawn with winners. `lp_earnings` is always populated — `{amount: \"0\", …}` while the round is open and accumulates as tickets sell, finalized at settlement. `ball_pool` is always populated; `winning_numbers` is null until the round is drawn; `prize_tiers` is null until per-tier payouts land (post-settlement, after the contract pipeline finishes).","example":{"id":"172","status":"settled","prize_pool":{"amount":"500000000000","decimals":6},"ticket_count":1001,"unique_participants":412,"winners_count":300,"top_prize_amount":{"amount":"183029000000","decimals":6},"top_prize_winners_count":1,"lp_earnings":{"amount":"1234567","decimals":6},"started_at":"2026-04-14T18:00:00.000Z","ended_at":"2026-04-15T18:00:00.000Z","settled_at":"2026-04-15T18:05:32.000Z","ball_pool":{"normals_max":49,"bonusball_max":26},"winning_numbers":{"normals":[3,17,25,38,49],"bonusball":7},"prize_tiers":[{"tier_id":0,"normal_matches":0,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":847},{"tier_id":1,"normal_matches":0,"bonusball_match":true,"payout":{"amount":"500000","decimals":6},"ticket_count":92},{"tier_id":2,"normal_matches":1,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":53},{"tier_id":3,"normal_matches":1,"bonusball_match":true,"payout":{"amount":"1000000","decimals":6},"ticket_count":6},{"tier_id":4,"normal_matches":2,"bonusball_match":false,"payout":{"amount":"2000000","decimals":6},"ticket_count":2},{"tier_id":5,"normal_matches":2,"bonusball_match":true,"payout":{"amount":"5000000","decimals":6},"ticket_count":1},{"tier_id":6,"normal_matches":3,"bonusball_match":false,"payout":{"amount":"10000000","decimals":6},"ticket_count":0},{"tier_id":7,"normal_matches":3,"bonusball_match":true,"payout":{"amount":"25000000","decimals":6},"ticket_count":0},{"tier_id":8,"normal_matches":4,"bonusball_match":false,"payout":{"amount":"50000000","decimals":6},"ticket_count":0},{"tier_id":9,"normal_matches":4,"bonusball_match":true,"payout":{"amount":"100000000","decimals":6},"ticket_count":0},{"tier_id":10,"normal_matches":5,"bonusball_match":false,"payout":{"amount":"250000000000","decimals":6},"ticket_count":0},{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}]}},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"RoundStatus":{"type":"string","enum":["active","settled"],"description":"Round lifecycle state. `active` covers DB `open` (selling tickets) and DB `locked` (drawing in progress). `settled` covers DB `settled` (payouts done)."},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"BallPool":{"type":"object","properties":{"normals_max":{"type":"integer","minimum":0,"maximum":9007199254740991},"bonusball_max":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["normals_max","bonusball_max"],"description":"Contract-configured ranges for this round's normal balls (1..normals_max) and bonusball (1..bonusball_max). Both values are always populated, including on the active round, since they're set when the round opens.","example":{"normals_max":49,"bonusball_max":26}},"WinningNumbers":{"type":"object","properties":{"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["normals","bonusball"],"description":"The 5 normal numbers + 1 bonusball drawn at settlement. Null on the Round resource until the round is drawn.","example":{"normals":[3,17,25,38,49],"bonusball":7}},"PrizeTier":{"type":"object","properties":{"tier_id":{"type":"integer","minimum":0,"maximum":11},"normal_matches":{"type":"integer","minimum":0,"maximum":5},"bonusball_match":{"type":"boolean"},"payout":{"$ref":"#/components/schemas/Amount"},"ticket_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["tier_id","normal_matches","bonusball_match","payout","ticket_count"],"description":"One of 12 prize tiers for a settled round. `tier_id = normal_matches * 2 + (bonusball_match ? 1 : 0)`. Tiers 0 and 2 are zero-payout (no bonus at low matches) but receive non-zero `ticket_count` for tickets that landed there. `payout` is the contract's gross per-ticket amount; per-ticket actual winnings (`Ticket.winnings_amount`) net out the round's referral share.","example":{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/rounds/{roundId}":{"get":{"operationId":"getV1RoundsByRoundId","tags":["Round"],"summary":"Get a round by id","description":"Single round with per-round aggregates (`ticket_count`, `unique_participants`, `winners_count`, `top_prize_amount`, `top_prize_winners_count`) and `started_at` derived from the previous round's `settled_at`.","responses":{"200":{"description":"The requested round","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/RoundId"},"status":{"$ref":"#/components/schemas/RoundStatus"},"prize_pool":{"$ref":"#/components/schemas/Amount"},"ticket_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"unique_participants":{"type":"integer","minimum":0,"maximum":9007199254740991},"winners_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"top_prize_amount":{"anyOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}]},"top_prize_winners_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"lp_earnings":{"$ref":"#/components/schemas/Amount"},"started_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"ended_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"settled_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"ball_pool":{"$ref":"#/components/schemas/BallPool"},"winning_numbers":{"anyOf":[{"$ref":"#/components/schemas/WinningNumbers"},{"type":"null"}]},"prize_tiers":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"$ref":"#/components/schemas/PrizeTier"}},{"type":"null"}]}},"required":["id","status","prize_pool","ticket_count","unique_participants","winners_count","top_prize_amount","top_prize_winners_count","lp_earnings","started_at","ended_at","settled_at","ball_pool","winning_numbers","prize_tiers"],"description":"A round of the lottery, with per-round aggregates folded in. `started_at` is derived from the previous round's `settled_at` (null for round 1). `ended_at` is the contract's drawing time. `top_prize_amount` is null until the round is drawn with winners. `lp_earnings` is always populated — `{amount: \"0\", …}` while the round is open and accumulates as tickets sell, finalized at settlement. `ball_pool` is always populated; `winning_numbers` is null until the round is drawn; `prize_tiers` is null until per-tier payouts land (post-settlement, after the contract pipeline finishes).","example":{"id":"172","status":"settled","prize_pool":{"amount":"500000000000","decimals":6},"ticket_count":1001,"unique_participants":412,"winners_count":300,"top_prize_amount":{"amount":"183029000000","decimals":6},"top_prize_winners_count":1,"lp_earnings":{"amount":"1234567","decimals":6},"started_at":"2026-04-14T18:00:00.000Z","ended_at":"2026-04-15T18:00:00.000Z","settled_at":"2026-04-15T18:05:32.000Z","ball_pool":{"normals_max":49,"bonusball_max":26},"winning_numbers":{"normals":[3,17,25,38,49],"bonusball":7},"prize_tiers":[{"tier_id":0,"normal_matches":0,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":847},{"tier_id":1,"normal_matches":0,"bonusball_match":true,"payout":{"amount":"500000","decimals":6},"ticket_count":92},{"tier_id":2,"normal_matches":1,"bonusball_match":false,"payout":{"amount":"0","decimals":6},"ticket_count":53},{"tier_id":3,"normal_matches":1,"bonusball_match":true,"payout":{"amount":"1000000","decimals":6},"ticket_count":6},{"tier_id":4,"normal_matches":2,"bonusball_match":false,"payout":{"amount":"2000000","decimals":6},"ticket_count":2},{"tier_id":5,"normal_matches":2,"bonusball_match":true,"payout":{"amount":"5000000","decimals":6},"ticket_count":1},{"tier_id":6,"normal_matches":3,"bonusball_match":false,"payout":{"amount":"10000000","decimals":6},"ticket_count":0},{"tier_id":7,"normal_matches":3,"bonusball_match":true,"payout":{"amount":"25000000","decimals":6},"ticket_count":0},{"tier_id":8,"normal_matches":4,"bonusball_match":false,"payout":{"amount":"50000000","decimals":6},"ticket_count":0},{"tier_id":9,"normal_matches":4,"bonusball_match":true,"payout":{"amount":"100000000","decimals":6},"ticket_count":0},{"tier_id":10,"normal_matches":5,"bonusball_match":false,"payout":{"amount":"250000000000","decimals":6},"ticket_count":0},{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}]},"$defs":{"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"RoundStatus":{"type":"string","enum":["active","settled"],"description":"Round lifecycle state. `active` covers DB `open` (selling tickets) and DB `locked` (drawing in progress). `settled` covers DB `settled` (payouts done)."},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"BallPool":{"type":"object","properties":{"normals_max":{"type":"integer","minimum":0,"maximum":9007199254740991},"bonusball_max":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["normals_max","bonusball_max"],"description":"Contract-configured ranges for this round's normal balls (1..normals_max) and bonusball (1..bonusball_max). Both values are always populated, including on the active round, since they're set when the round opens.","example":{"normals_max":49,"bonusball_max":26}},"WinningNumbers":{"type":"object","properties":{"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["normals","bonusball"],"description":"The 5 normal numbers + 1 bonusball drawn at settlement. Null on the Round resource until the round is drawn.","example":{"normals":[3,17,25,38,49],"bonusball":7}},"PrizeTier":{"type":"object","properties":{"tier_id":{"type":"integer","minimum":0,"maximum":11},"normal_matches":{"type":"integer","minimum":0,"maximum":5},"bonusball_match":{"type":"boolean"},"payout":{"$ref":"#/components/schemas/Amount"},"ticket_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["tier_id","normal_matches","bonusball_match","payout","ticket_count"],"description":"One of 12 prize tiers for a settled round. `tier_id = normal_matches * 2 + (bonusball_match ? 1 : 0)`. Tiers 0 and 2 are zero-payout (no bonus at low matches) but receive non-zero `ticket_count` for tickets that landed there. `payout` is the contract's gross per-ticket amount; per-ticket actual winnings (`Ticket.winnings_amount`) net out the round's referral share.","example":{"tier_id":11,"normal_matches":5,"bonusball_match":true,"payout":{"amount":"500000000000","decimals":6},"ticket_count":1}}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"404":{"description":"Resource not found (`error.code = not_found`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"roundId","required":true}]}},"/v1/rounds/{roundId}/tickets":{"get":{"operationId":"getV1RoundsByRoundIdTickets","tags":["Round"],"summary":"List tickets in a round","description":"Paginated tickets bought against the given round, newest first (`id DESC`). Returns 404 if `roundId` doesn't exist (PK existence check at handler entry).","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"schema":{"type":"string"},"in":"path","name":"roundId","required":true}],"responses":{"200":{"description":"Paginated tickets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Ticket":{"type":"object","properties":{"id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"wallet":{"$ref":"#/components/schemas/Address"},"buyer":{"$ref":"#/components/schemas/Address"},"round_id":{"$ref":"#/components/schemas/RoundId"},"user_ticket_id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991},"matched_normals":{"anyOf":[{"type":"integer","minimum":0,"maximum":5},{"type":"null"}]},"bonusball_match":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"winnings_amount":{"anyOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}]},"claimed":{"type":"boolean"},"claimed_tx_hash":{"anyOf":[{"$ref":"#/components/schemas/TxHash"},{"type":"null"}]},"tx_hash":{"$ref":"#/components/schemas/TxHash"},"block_number":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"$ref":"#/components/schemas/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","winnings_amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"description":"A single ticket bought against a round. Fields `matched_normals`, `bonusball_match`, and `winnings_amount` are null until the round is drawn. `wallet` is the recipient (owner); `buyer` is the address that submitted the purchase (may differ for gifted/agent buys).","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"winnings_amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"}},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"404":{"description":"Resource not found (`error.code = not_found`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/rounds/{roundId}/wins":{"get":{"operationId":"getV1RoundsByRoundIdWins","tags":["Round"],"summary":"List wins in a round","description":"Paginated winning tickets in the given round, sorted by `winnings_amount DESC, id DESC`. Pass `?claimed=false` to return only unclaimed wins or `?claimed=true` for already-claimed wins; omit to return both. Returns 404 if `roundId` doesn't exist.","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"claimed","in":"query","required":false,"description":"Filter wins by claim status. Pass `true` for claimed wins or `false` for unclaimed wins. Omit to return both.","schema":{"type":"boolean"}},{"schema":{"type":"string"},"in":"path","name":"roundId","required":true}],"responses":{"200":{"description":"Paginated wins","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Win"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Win":{"type":"object","properties":{"id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"wallet":{"$ref":"#/components/schemas/Address"},"buyer":{"$ref":"#/components/schemas/Address"},"round_id":{"$ref":"#/components/schemas/RoundId"},"user_ticket_id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991},"matched_normals":{"type":"integer","minimum":0,"maximum":5},"bonusball_match":{"type":"boolean"},"amount":{"$ref":"#/components/schemas/Amount"},"claimed":{"type":"boolean"},"claimed_tx_hash":{"anyOf":[{"$ref":"#/components/schemas/TxHash"},{"type":"null"}]},"tx_hash":{"$ref":"#/components/schemas/TxHash"},"block_number":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"$ref":"#/components/schemas/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"description":"A winning ticket. Same shape as Ticket with `winnings_amount` renamed `amount` and the three round-drawn fields (`amount`, `matched_normals`, `bonusball_match`) guaranteed non-null. `claimed_tx_hash` stays nullable — a Win can be unclaimed.","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"}},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"404":{"description":"Resource not found (`error.code = not_found`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/wallets/{address}/stats":{"get":{"operationId":"getV1WalletsByAddressStats","tags":["Wallet"],"summary":"Wallet aggregate stats","description":"Recipient-keyed aggregate stats for a wallet (total tickets, wins, winnings, spent, rounds played, first/last seen) plus lifetime gross referral earnings (fees + claim bonuses + unclaimed pending winnings). Unknown wallets return 200 with zeros + null timestamps — no pre-flight existence check needed. Address input accepts any case; output is EIP-55.","responses":{"200":{"description":"Wallet aggregate stats","content":{"application/json":{"schema":{"type":"object","properties":{"address":{"$ref":"#/components/schemas/Address"},"total_tickets":{"type":"integer","minimum":0,"maximum":9007199254740991},"total_wins":{"type":"integer","minimum":0,"maximum":9007199254740991},"total_winnings":{"$ref":"#/components/schemas/Amount"},"total_spent":{"$ref":"#/components/schemas/Amount"},"total_referral_earnings":{"$ref":"#/components/schemas/Amount"},"rounds_played":{"type":"integer","minimum":0,"maximum":9007199254740991},"first_seen_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"$ref":"#/components/schemas/Timestamp"},{"type":"null"}]}},"required":["address","total_tickets","total_wins","total_winnings","total_spent","total_referral_earnings","rounds_played","first_seen_at","last_seen_at"],"description":"Aggregate ticket, winnings, and referral stats for a wallet. Ticket and winnings figures are recipient-keyed (wallet that owns the tickets, not the buyer). `total_referral_earnings` is lifetime gross income earned by referring other wallets (purchase fees + claim bonuses + still-unclaimed pending winnings). Unknown wallets return zeros with null timestamps.","example":{"address":"0x1111111111111111111111111111111111111111","total_tickets":12,"total_wins":3,"total_winnings":{"amount":"150000000","decimals":6},"total_spent":{"amount":"60000000","decimals":6},"total_referral_earnings":{"amount":"123456","decimals":6},"rounds_played":7,"first_seen_at":"2026-01-15T10:00:00.000Z","last_seen_at":"2026-04-29T12:34:56.000Z"},"$defs":{"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"address","required":true}]}},"/v1/wallets/{address}/tickets":{"get":{"operationId":"getV1WalletsByAddressTickets","tags":["Wallet"],"summary":"List wallet tickets","description":"Paginated tickets owned by the wallet (recipient-keyed), newest first (`id DESC`). Unknown wallets return 200 + empty `data: []`.","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"schema":{"type":"string"},"in":"path","name":"address","required":true}],"responses":{"200":{"description":"Paginated tickets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Ticket":{"type":"object","properties":{"id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"wallet":{"$ref":"#/components/schemas/Address"},"buyer":{"$ref":"#/components/schemas/Address"},"round_id":{"$ref":"#/components/schemas/RoundId"},"user_ticket_id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991},"matched_normals":{"anyOf":[{"type":"integer","minimum":0,"maximum":5},{"type":"null"}]},"bonusball_match":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"winnings_amount":{"anyOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}]},"claimed":{"type":"boolean"},"claimed_tx_hash":{"anyOf":[{"$ref":"#/components/schemas/TxHash"},{"type":"null"}]},"tx_hash":{"$ref":"#/components/schemas/TxHash"},"block_number":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"$ref":"#/components/schemas/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","winnings_amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"description":"A single ticket bought against a round. Fields `matched_normals`, `bonusball_match`, and `winnings_amount` are null until the round is drawn. `wallet` is the recipient (owner); `buyer` is the address that submitted the purchase (may differ for gifted/agent buys).","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"winnings_amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"}},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/wallets/{address}/tickets/rounds/{roundId}":{"get":{"operationId":"getV1WalletsByAddressTicketsRoundsByRoundId","tags":["Wallet"],"summary":"List wallet tickets in a specific round","description":"Wallet's tickets scoped to a single round. Returns 404 if `roundId` doesn't exist; returns 200 + empty `data: []` for an unknown wallet.","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"schema":{"type":"string"},"in":"path","name":"address","required":true},{"schema":{"type":"string"},"in":"path","name":"roundId","required":true}],"responses":{"200":{"description":"Paginated tickets in the round","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Ticket":{"type":"object","properties":{"id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"wallet":{"$ref":"#/components/schemas/Address"},"buyer":{"$ref":"#/components/schemas/Address"},"round_id":{"$ref":"#/components/schemas/RoundId"},"user_ticket_id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991},"matched_normals":{"anyOf":[{"type":"integer","minimum":0,"maximum":5},{"type":"null"}]},"bonusball_match":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"winnings_amount":{"anyOf":[{"$ref":"#/components/schemas/Amount"},{"type":"null"}]},"claimed":{"type":"boolean"},"claimed_tx_hash":{"anyOf":[{"$ref":"#/components/schemas/TxHash"},{"type":"null"}]},"tx_hash":{"$ref":"#/components/schemas/TxHash"},"block_number":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"$ref":"#/components/schemas/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","winnings_amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"description":"A single ticket bought against a round. Fields `matched_normals`, `bonusball_match`, and `winnings_amount` are null until the round is drawn. `wallet` is the recipient (owner); `buyer` is the address that submitted the purchase (may differ for gifted/agent buys).","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"winnings_amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"}},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"404":{"description":"Resource not found (`error.code = not_found`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/wallets/{address}/wins":{"get":{"operationId":"getV1WalletsByAddressWins","tags":["Wallet"],"summary":"List wallet wins","description":"Paginated winning tickets for the wallet, sorted by `winnings_amount DESC, id DESC`. Uses the partial index `idx_tickets_wallet_wins_partial` for performance. Pass `?claimed=false` to return only unclaimed wins (useful for claim flows) or `?claimed=true` for already-claimed wins; omit to return both. Unknown wallets return 200 + empty `data: []`.","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"claimed","in":"query","required":false,"description":"Filter wins by claim status. Pass `true` for claimed wins or `false` for unclaimed wins. Omit to return both.","schema":{"type":"boolean"}},{"schema":{"type":"string"},"in":"path","name":"address","required":true}],"responses":{"200":{"description":"Paginated wins","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Win"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Win":{"type":"object","properties":{"id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"wallet":{"$ref":"#/components/schemas/Address"},"buyer":{"$ref":"#/components/schemas/Address"},"round_id":{"$ref":"#/components/schemas/RoundId"},"user_ticket_id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991},"matched_normals":{"type":"integer","minimum":0,"maximum":5},"bonusball_match":{"type":"boolean"},"amount":{"$ref":"#/components/schemas/Amount"},"claimed":{"type":"boolean"},"claimed_tx_hash":{"anyOf":[{"$ref":"#/components/schemas/TxHash"},{"type":"null"}]},"tx_hash":{"$ref":"#/components/schemas/TxHash"},"block_number":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"$ref":"#/components/schemas/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"description":"A winning ticket. Same shape as Ticket with `winnings_amount` renamed `amount` and the three round-drawn fields (`amount`, `matched_normals`, `bonusball_match`) guaranteed non-null. `claimed_tx_hash` stays nullable — a Win can be unclaimed.","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"}},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}},"/v1/wallets/{address}/wins/rounds/{roundId}":{"get":{"operationId":"getV1WalletsByAddressWinsRoundsByRoundId","tags":["Wallet"],"summary":"List wallet wins in a specific round","description":"Wallet's winning tickets scoped to a single round. Returns 404 if `roundId` doesn't exist; returns 200 + empty `data: []` for an unknown wallet.","parameters":[{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...` to walk the list.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return per page. Defaults to 50, clamped to [1, 100].","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"schema":{"type":"string"},"in":"path","name":"address","required":true},{"schema":{"type":"string"},"in":"path","name":"roundId","required":true}],"responses":{"200":{"description":"Paginated wins in the round","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Win"}},"next_cursor":{"anyOf":[{"$ref":"#/components/schemas/Cursor"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"$defs":{"Win":{"type":"object","properties":{"id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"wallet":{"$ref":"#/components/schemas/Address"},"buyer":{"$ref":"#/components/schemas/Address"},"round_id":{"$ref":"#/components/schemas/RoundId"},"user_ticket_id":{"type":"string","minLength":1,"pattern":"^\\d+$"},"normals":{"minItems":5,"maxItems":5,"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bonusball":{"type":"integer","minimum":0,"maximum":9007199254740991},"matched_normals":{"type":"integer","minimum":0,"maximum":5},"bonusball_match":{"type":"boolean"},"amount":{"$ref":"#/components/schemas/Amount"},"claimed":{"type":"boolean"},"claimed_tx_hash":{"anyOf":[{"$ref":"#/components/schemas/TxHash"},{"type":"null"}]},"tx_hash":{"$ref":"#/components/schemas/TxHash"},"block_number":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"$ref":"#/components/schemas/Timestamp"}},"required":["id","wallet","buyer","round_id","user_ticket_id","normals","bonusball","matched_normals","bonusball_match","amount","claimed","claimed_tx_hash","tx_hash","block_number","created_at"],"description":"A winning ticket. Same shape as Ticket with `winnings_amount` renamed `amount` and the three round-drawn fields (`amount`, `matched_normals`, `bonusball_match`) guaranteed non-null. `claimed_tx_hash` stays nullable — a Win can be unclaimed.","example":{"id":"12345","wallet":"0x1111111111111111111111111111111111111111","buyer":"0x2222222222222222222222222222222222222222","round_id":"172","user_ticket_id":"47","normals":[3,17,25,38,49],"bonusball":7,"matched_normals":4,"bonusball_match":true,"amount":{"amount":"183029000000","decimals":6},"claimed":true,"claimed_tx_hash":"0xdeadbeef00000000000000000000000000000000000000000000000000000000","tx_hash":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef","block_number":22847291,"created_at":"2026-04-15T18:32:14.000Z"}},"Address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"EVM address. Output is always EIP-55 checksummed; input accepts any case, validated shape-only.","example":"0x1111111111111111111111111111111111111111"},"RoundId":{"type":"string","minLength":1,"pattern":"^\\d+$","description":"Round identifier (DB drawing_id, stringified).","example":"172"},"Amount":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+$"},"decimals":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","decimals"],"description":"Token amount in raw smallest-unit form. Divide by 10**decimals for the human-readable value.","example":{"amount":"1000000","decimals":6}},"TxHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"EVM transaction hash (32 bytes, 0x-prefixed).","example":"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},"Timestamp":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"ISO 8601 UTC timestamp with millisecond precision and `Z` suffix.","example":"2026-04-29T12:34:56.000Z"},"Cursor":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9_-]+$","description":"Opaque pagination cursor. Treat as a black box; pass `next_cursor` from a paginated response back via `?cursor=...`.","example":"eyJzb3J0X2tleV92YWx1ZSI6IjE3MiIsImlkIjoiMTIzIn0"}}}}}},"400":{"description":"Bad request — `error.code` is one of `invalid_request`, `invalid_address`, or `invalid_cursor`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"401":{"description":"Unauthorized — `error.code = invalid_api_key`. Returned when a Bearer key is provided but doesn't match a known active key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"403":{"description":"Forbidden — `error.code` is one of `revoked_api_key` or `key_environment_mismatch`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"404":{"description":"Resource not found (`error.code = not_found`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"405":{"description":"Method not allowed (`error.code = method_not_allowed`). Path exists, but not for this HTTP method — see the `Allow` response header for supported methods.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}},"429":{"description":"Rate limit exceeded (`error.code = rate_limited`).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","invalid_address","invalid_cursor","unauthorized","invalid_api_key","revoked_api_key","key_environment_mismatch","not_found","method_not_allowed","validation_failed","rate_limited","internal_error","upstream_unavailable"]},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"],"description":"Standard error response envelope. Every non-2xx response carries this shape with one of the canonical `code` values.","example":{"error":{"code":"invalid_address","message":"Address must be 0x followed by 40 hex chars","request_id":"req_abc123"}}}}}}}}}}}