{"openapi":"3.1.0","info":{"title":"x402casinos API","version":"1.0.0","description":"A casino built for autonomous AI agents. Pay per play with x402 (USDC on Base), verify every roll with commit-reveal fairness, withdraw on-chain.","x-guidance":"x402casinos is a provably-fair casino designed for autonomous AI agents.\n\nPAYMENT MODEL\n- Every paid endpoint returns HTTP 402 with a base64 `PAYMENT-REQUIRED` header on first call. Pay with EIP-3009 USDC on Base (or Base Sepolia in test) and resubmit with an `X-PAYMENT` (or `payment-signature`) header. The payer wallet is recovered cryptographically from the EIP-3009 authorization — never trust wallet fields in request bodies.\n- Game prices are dynamic via `?stake=micro|standard|whale` ($0.10 / $1.00 / $10.00). Other paid routes (discovery, balance, bet status) are fixed at $0.01; withdraw fee is $0.05.\n\nPLAY → SETTLE → REVEAL FLOW\n1. Snapshot `GET /api/v1/seed/commit` (free) before betting — that hash commits the server seed.\n2. Pick a game (`POST /api/v1/games/:game?stake=...`) with a `client_seed` and monotonically increasing `nonce`. The response includes `outcome`, `payout_micro`, and verification fields. Status is `settling` until the facilitator confirms on-chain.\n3. Confirm with `GET /api/v1/bets/{id}` — status flips to `settled` and the payout is credited to your in-house balance.\n4. Cash out with `POST /api/v1/withdraw` ({ amount_micro }) to the same payer address.\n\nIDENTITY (SIWE / SIWX)\n- The `/api/v1/dashboard/*` routes are wallet-owner-only and gated by a SIWE session cookie (`siwe-session`). They are NOT x402-paid. To use them: `GET /api/auth/siwe/nonce`, sign an EIP-4361 message, then `POST /api/auth/siwe/verify` to set the cookie. Most autonomous agents will only need the x402 routes — SIWE is for the human-facing dashboard.\n\nFAIRNESS\n- Server seeds are committed in advance and revealed via `GET /api/v1/seed/reveal?seed_id=...` once rotated. Outcomes are HMAC-SHA256(server_seed, \"{client_seed}:{nonce}\"), so any past bet can be replayed offline.\n\nDISCOVERY\n- This OpenAPI doc is canonical. `/.well-known/x402` is a v1 fallback listing payable resources. `/.well-known/api-catalog`, `/.well-known/ucp`, `/.well-known/skill.json`, and `/.well-known/agent-skills/index.json` are alternative agent-friendly views.","contact":{"email":"support@x402casinos.com"},"license":{"name":"Terms of Service","url":"https://x402casinos.com/terms"}},"servers":[{"url":"https://x402casinos.com"}],"tags":[{"name":"discovery","description":"Manifest and capability discovery."},{"name":"games","description":"Provably-fair casino games (x402-paid)."},{"name":"wallet","description":"Balance, bet status, and withdrawal (x402-paid)."},{"name":"fairness","description":"Commit-reveal seed lifecycle (free)."},{"name":"auth","description":"Sign-In With Ethereum (EIP-4361)."},{"name":"dashboard","description":"Wallet-owner dashboard (SIWX-gated)."}],"components":{"securitySchemes":{"siwx":{"type":"apiKey","in":"cookie","name":"siwe-session","description":"Sign-In With X (EIP-4361). Obtain via GET /api/auth/siwe/nonce → POST /api/auth/siwe/verify. Cookie lifetime is 7 days."}},"schemas":{"Error402":{"type":"object","description":"x402 PAYMENT-REQUIRED body. The same payload (base64-encoded) is also returned in the PAYMENT-REQUIRED response header.","required":["x402Version","accepts"],"properties":{"x402Version":{"type":"integer","const":2},"resource":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"description":{"type":"string"},"mimeType":{"type":"string"}}},"accepts":{"type":"array","items":{"type":"object","required":["scheme","network","amount","asset","payTo"],"properties":{"scheme":{"type":"string","const":"exact"},"network":{"type":"string","example":"eip155:8453"},"amount":{"type":"string","description":"USDC smallest-unit (1e-6) integer string"},"asset":{"type":"string","description":"USDC contract address"},"payTo":{"type":"string","description":"Casino receiving wallet"},"maxTimeoutSeconds":{"type":"integer"}}}},"extensions":{"type":"object","description":"Optional per-resource extension blocks. Includes `bazaar.schema` describing input/output for the AgentCash bazaar.","properties":{"bazaar":{"type":"object"}}}}},"BetBodyBase":{"type":"object","required":["client_seed","nonce"],"properties":{"client_seed":{"type":"string","minLength":1,"maxLength":128,"description":"Caller-chosen seed (1–128 chars). Combined with the server seed via HMAC-SHA256 to derive the outcome."},"nonce":{"type":"integer","minimum":0,"description":"Monotonic per (wallet, server_seed_id, client_seed). Replays return 409."}}},"CoinflipBody":{"allOf":[{"$ref":"#/components/schemas/BetBodyBase"},{"type":"object","required":["choice"],"properties":{"choice":{"type":"string","enum":["heads","tails"],"description":"Side to bet on."}}}]},"DiceBody":{"allOf":[{"$ref":"#/components/schemas/BetBodyBase"},{"type":"object","required":["threshold","direction"],"properties":{"threshold":{"type":"integer","minimum":2,"maximum":99,"description":"Roll boundary 2–99 (the rolled value is 1–100)."},"direction":{"type":"string","enum":["over","under"]}}}]},"RouletteBody":{"allOf":[{"$ref":"#/components/schemas/BetBodyBase"},{"type":"object","required":["bet"],"properties":{"bet":{"description":"Roulette bet (single number 0–36, color, parity, dozen, etc.).","oneOf":[{"type":"integer","minimum":0,"maximum":36},{"type":"string","enum":["red","black","even","odd","low","high"]},{"type":"object","required":["type","value"],"properties":{"type":{"type":"string","enum":["number","color","parity","range","dozen","column"]},"value":{}}}]}}}]},"SlotsBody":{"$ref":"#/components/schemas/BetBodyBase"},"WithdrawBody":{"type":"object","required":["amount_micro"],"properties":{"amount_micro":{"type":"integer","minimum":1,"description":"Amount to withdraw in USDC micro-units (1 USDC = 1_000_000)."}}},"SiweVerifyBody":{"type":"object","required":["message","signature"],"properties":{"message":{"type":"string","description":"EIP-4361 SIWE message (must include the nonce from /api/auth/siwe/nonce)."},"signature":{"type":"string","description":"0x-prefixed EIP-191 signature."}}},"NotificationsBody":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"events":{"type":"object","description":"Per-event opt-in flags.","additionalProperties":{"type":"boolean"}}}},"BetResponse":{"type":"object","properties":{"bet_id":{"type":"string","format":"uuid"},"game":{"type":"string"},"stake_tier":{"type":"string","enum":["micro","standard","whale"]},"stake_micro":{"type":"integer"},"outcome":{},"payout_micro":{"type":"integer"},"status":{"type":"string","enum":["settling","settled","voided"]},"verification":{"type":"object","properties":{"server_seed_hash":{"type":"string"},"server_seed_id":{"type":"string"},"client_seed":{"type":"string"},"nonce":{"type":"integer"}}}}}}},"paths":{"/api/v1":{"get":{"operationId":"getDiscovery","summary":"Agent-facing discovery manifest (paid).","tags":["discovery"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.01"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"fetch-discovery","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"chain":{"type":"string"},"asset":{"type":"string"},"pay_to":{"type":"string"},"games":{"type":"array","items":{"type":"string"}}}}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"parameters":[{"name":"Accept","in":"header","required":false,"schema":{"type":"string","default":"application/json"},"description":"Response content negotiation. Always JSON in practice."}]}},"/api/v1/games":{"get":{"operationId":"listGames","summary":"Public game manifest with stakes, descriptions, and payouts.","tags":["discovery"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/games/coinflip":{"post":{"operationId":"playCoinflip","summary":"Play coin flip (heads/tails).","tags":["games"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.10","max":"10.00"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"play-coinflip","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetResponse"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"parameters":[{"name":"stake","in":"query","required":true,"schema":{"type":"string","enum":["micro","standard","whale"]},"description":"Stake tier — also determines the x402 price ($0.10 / $1.00 / $10.00)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoinflipBody"}}}}}},"/api/v1/games/dice":{"post":{"operationId":"playDice","summary":"Bet on a dice roll over/under a threshold (1–100).","tags":["games"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.10","max":"10.00"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"play-dice","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetResponse"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"parameters":[{"name":"stake","in":"query","required":true,"schema":{"type":"string","enum":["micro","standard","whale"]},"description":"Stake tier — also determines the x402 price ($0.10 / $1.00 / $10.00)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiceBody"}}}}}},"/api/v1/games/roulette":{"post":{"operationId":"playRoulette","summary":"Play single-zero European roulette (0–36).","tags":["games"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.10","max":"10.00"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"play-roulette","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetResponse"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"parameters":[{"name":"stake","in":"query","required":true,"schema":{"type":"string","enum":["micro","standard","whale"]},"description":"Stake tier — also determines the x402 price ($0.10 / $1.00 / $10.00)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouletteBody"}}}}}},"/api/v1/games/slots":{"post":{"operationId":"playSlots","summary":"Play 3-reel slots (6 symbols).","tags":["games"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.10","max":"10.00"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"play-slots","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetResponse"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"parameters":[{"name":"stake","in":"query","required":true,"schema":{"type":"string","enum":["micro","standard","whale"]},"description":"Stake tier — also determines the x402 price ($0.10 / $1.00 / $10.00)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlotsBody"}}}}}},"/api/v1/balance":{"get":{"operationId":"getBalance","summary":"Read the in-house USDC balance for the x402 payer wallet.","tags":["wallet"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.01"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"read-balance","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"wallet":{"type":"string"},"usdc_micro":{"type":"integer"},"updated_at":{"type":"string","format":"date-time"}}}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"parameters":[{"name":"Accept","in":"header","required":false,"schema":{"type":"string","default":"application/json"},"description":"Response content negotiation. Always JSON in practice."}]}},"/api/v1/bets/{id}":{"get":{"operationId":"getBet","summary":"Fetch a specific bet by id (only the payer can view their own bets).","tags":["wallet"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.01"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"read-bet-status","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BetResponse"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}},"403":{"description":"Forbidden — bet belongs to a different payer."},"404":{"description":"Not found."}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/v1/withdraw":{"post":{"operationId":"withdraw","summary":"Withdraw USDC on-chain to the x402 payer address. Destination is the payer wallet — never a body field.","tags":["wallet"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.05"},"protocols":[{"x402":{}},{"mpp":{"method":"exact","intent":"withdraw-usdc","currency":"USDC"}}]},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"withdrawal_id":{"type":"string","format":"uuid"},"tx_hash":{"type":"string"},"status":{"type":"string"},"explorer":{"type":"string","format":"uri"}}}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error402"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawBody"}}}}}},"/api/v1/seed/commit":{"get":{"operationId":"getSeedCommit","summary":"Active server-seed commitment (hash). Snapshot before betting; also serves as a liveness probe.","tags":["fairness"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"seed_id":{"type":"string"},"seed_hash":{"type":"string","description":"SHA-256 hex of the active server seed."},"committed_at":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/seed/reveal":{"get":{"operationId":"getSeedReveal","summary":"Reveal the raw bytes of a rotated server seed. Locked until rotation.","tags":["fairness"],"parameters":[{"name":"seed_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"seed_id":{"type":"string"},"seed":{"type":"string","description":"Hex bytes."},"seed_hash":{"type":"string"},"rotated_at":{"type":"string","format":"date-time"}}}}}},"423":{"description":"Seed still active — locked until rotation."}}}},"/api/auth/siwe/nonce":{"get":{"operationId":"siweNonce","summary":"Issue a SIWE nonce (10-min cookie). Step 1 of dashboard sign-in.","tags":["auth"],"responses":{"200":{"description":"Plain-text nonce.","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/auth/siwe/verify":{"post":{"operationId":"siweVerify","summary":"Verify EIP-4361 SIWE message and signature; sets the siwe-session cookie (7 days).","tags":["auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiweVerifyBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"address":{"type":"string"}}}}}},"401":{"description":"Signature invalid or nonce mismatch."},"403":{"description":"Address blocked (OFAC)."}}}},"/api/auth/siwe/me":{"get":{"operationId":"siweMe","summary":"Return the current SIWE session (or { authenticated: false }).","tags":["auth"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"authenticated":{"type":"boolean"},"address":{"type":"string"}}}}}}}}},"/api/auth/siwe/logout":{"post":{"operationId":"siweLogout","summary":"Clear the SIWE session cookie.","tags":["auth"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/dashboard/bets":{"get":{"operationId":"dashboardBets","summary":"Paginated bet history for the authenticated wallet.","tags":["dashboard"],"security":[{"siwx":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated — SIWE session cookie missing or expired."}},"parameters":[{"name":"game","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"result","in":"query","schema":{"type":"string","enum":["win","loss"]}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}]}},"/api/v1/dashboard/withdrawals":{"get":{"operationId":"dashboardWithdrawals","summary":"Paginated withdrawal history for the authenticated wallet.","tags":["dashboard"],"security":[{"siwx":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated — SIWE session cookie missing or expired."}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}]}},"/api/v1/dashboard/withdraw":{"post":{"operationId":"dashboardWithdraw","summary":"On-chain USDC payout to the authenticated wallet. Free for SIWE session owners.","tags":["dashboard"],"security":[{"siwx":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated — SIWE session cookie missing or expired."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawBody"}}}}}},"/api/v1/dashboard/summary":{"get":{"operationId":"dashboardSummary","summary":"KPI snapshot for the authenticated wallet (balance, lifetime PnL, win rate).","tags":["dashboard"],"security":[{"siwx":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated — SIWE session cookie missing or expired."}}}},"/api/v1/dashboard/notifications":{"get":{"operationId":"dashboardNotificationsGet","summary":"Current email notification preferences for the authenticated wallet.","tags":["dashboard"],"security":[{"siwx":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated — SIWE session cookie missing or expired."}}},"post":{"operationId":"dashboardNotificationsUpsert","summary":"Upsert notification preferences; sends a verification email.","tags":["dashboard"],"security":[{"siwx":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated — SIWE session cookie missing or expired."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationsBody"}}}}}}}}