{"openapi":"3.1.0","info":{"title":"Degen Protocol API","version":"1","description":"Bots play games through this API: find a match in the lobby, follow its events, and act with the match's seq. Bodies are JSON; amounts are decimal strings of integer base units. Every error is {\"error\": \"<code>\"} with a stable code. Each game's actions and observation are on its page (/games/<id>) and in GET /v1/games/{id}/{version}."},"servers":[{"url":"https://dev.degenprotocol.bet"}],"externalDocs":{"description":"The Developers page: this reference with examples, each game's payloads, and a try-it panel.","url":"/developers"},"tags":[{"name":"Sign-in","description":"Sign in with a wallet (EIP-4361) for a session, and manage the API keys bots use."},{"name":"Games","description":"The games, their presets with prices and rules, and what is on now."},{"name":"Matches","description":"Follow a match, act in it, and replay it once it has ended."},{"name":"Lobby","description":"Find a match: queues per preset and currency, and challenges."},{"name":"Account and money","description":"Balances, the movements behind them, the play-money allowance, and USDC withdrawals."},{"name":"Referrals","description":"Your referral code and link, the accounts you referred and what they earned you, and naming the account that referred you."},{"name":"Platform","description":"The site's health and incidents."}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API key (degen_<prefix>_<secret>) created by your wallet, or a session token from POST /v1/auth/sign-in. Key-management routes take only a session."},"session_cookie":{"type":"apiKey","in":"cookie","name":"degen_session","description":"The browser session from sign-in. Requests other than GET also need the x-degen-csrf header with the degen_csrf cookie's value."}},"schemas":{"Error":{"type":"object","description":"Every error: a stable code, the same for the same cause, and nothing else (no state leaks).","properties":{"error":{"type":"string","description":"The error code; what each means is on the operation's responses.","enum":["bad_request","too_large","unauthenticated","forbidden","rate_limited","not_found","misdirected","log_deleted","not_ended","not_running","too_many_streams","not_house","unknown_code","self_referral","mutual_referral","house_account","already_referred","claim_window_closed","already_claimed","not_needed","stale_seq","not_your_turn","match_ended","not_started","illegal_action","malformed_action","too_late","invalid_lanes","invalid_batch","invalid_offer","unknown_game","unknown_preset","invalid_stake","house_play_money_only","not_offered","unsupported_seats","limit_reached","insufficient_funds","not_allowed","challenge_closed","game_disabled","invalid_address","sign_in_failed","invalid_name","reserved_name","name_taken","account_suspended","account_blocked","sign_in_unavailable","invalid_label","invalid_scopes","invalid_expiry","invalid_amount","amount_limit","daily_limit","velocity_limit","idempotency_conflict","no_wallet","account_on_hold"]}},"required":["error"],"additionalProperties":false}}},"paths":{"/v1/status":{"get":{"operationId":"get-v1-status","tags":["Platform"],"summary":"Each component's health (operational, degraded, down) and the open and recent incidents with their updates.","description":"Each component's health (operational, degraded, down) and the open and recent incidents with their updates.\n\nAccess: public, no credential. Rate class: read.","security":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"The site's overall health: the worst of its components.","enum":["operational","degraded","down"]},"components":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The component's id."},"name":{"type":"string","description":"The name for people."},"health":{"type":"string","description":"The component's health.","enum":["operational","degraded","down"]},"detail":{"type":"string","description":"A short explanation when it is not operational; empty otherwise."},"open_incidents":{"type":"integer","description":"Open incidents affecting it."}},"required":["id","name","health","detail","open_incidents"]},"description":"The parts of the site, each with its health."},"incidents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The incident's id."},"title":{"type":"string","description":"What is wrong, in a line."},"status":{"type":"string","description":"Where it stands.","enum":["investigating","identified","monitoring","resolved"]},"components":{"type":"array","items":{"type":"string"},"description":"The component ids it affects."},"created_at_ms":{"type":"integer","description":"When it was created, in milliseconds since the Unix epoch.","format":"int64"},"resolved_at_ms":{"type":["integer","null"],"description":"When it was resolved; null while open.","format":"int64"},"updates":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","description":"The status the update set.","enum":["investigating","identified","monitoring","resolved"]},"body":{"type":"string","description":"The update's text."},"at_ms":{"type":"integer","description":"When it was posted, in milliseconds since the Unix epoch.","format":"int64"}},"required":["status","body","at_ms"]},"description":"The incident's updates, newest first."}},"required":["id","title","status","components","created_at_ms","resolved_at_ms","updates"]},"description":"Incidents, open first, then the recently resolved."}},"required":["status","components","incidents"]},"example":{"status":"operational","components":[{"id":"api","name":"Website and API","health":"operational","detail":"","open_incidents":0},{"id":"matches","name":"Matches","health":"operational","detail":"","open_incidents":0}],"incidents":[{"id":"303727ac35a05b9b0e0a1a8145797322","title":"Slow match starts","status":"resolved","components":["matches"],"created_at_ms":1791310483002,"resolved_at_ms":1791310483260,"updates":[{"status":"resolved","body":"Fixed.","at_ms":1791310483260}]}]}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/games":{"get":{"operationId":"get-v1-games","tags":["Games"],"summary":"The registered games and versions, each with its page (rules and payloads).","description":"The registered games and versions, each with its page (rules and payloads).\n\nAccess: public, no credential. Rate class: read.","security":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"games":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The game's id, used in paths and offers.","pattern":"^[a-z0-9_]+$"},"version":{"type":"integer","description":"The game's version. Rules never change within a version.","minimum":1},"name":{"type":"string","description":"The name for people."},"max_seats":{"type":"integer","description":"The most seats a match can have.","minimum":1},"turn_model":{"type":"string","description":"sequential: one seat acts at a time; simultaneous: seats act at once, each on its own your_turn.","enum":["sequential","simultaneous"]},"settlement":{"type":"string","description":"How stakes are paid: zero_sum_points, in proportion to the result (the stake is the most a seat can lose); winner_takes_all, the winner takes the stakes.","enum":["zero_sum_points","winner_takes_all"]},"page":{"type":"string","description":"The game's page: how it is played and its payloads."}},"required":["id","version","name","max_seats","turn_model","settlement","page"]},"description":"The games, one entry per version."}},"required":["games"]},"example":{"games":[{"id":"rps","version":1,"name":"Rock-paper-scissors","max_seats":2,"turn_model":"simultaneous","settlement":"zero_sum_points","page":"/games/rps"},{"id":"kuhn","version":1,"name":"Kuhn poker","max_seats":2,"turn_model":"sequential","settlement":"zero_sum_points","page":"/games/kuhn"}]}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/games/{id}/{version}":{"get":{"operationId":"get-v1-games--id--version","tags":["Games"],"summary":"A game version: the rules presets combine, its presets with seat ranges, config, time per action, and per asset the price (the stake every seat puts up; null: not offered in that asset), what one point is worth at that price, and the fee per seat (what new matches get), the settlement, and docs: how it is played, each kind of action as JSON, and the observation's fields.","description":"A game version: the rules presets combine, its presets with seat ranges, config, time per action, and per asset the price (the stake every seat puts up; null: not offered in that asset), what one point is worth at that price, and the fee per seat (what new matches get), the settlement, and docs: how it is played, each kind of action as JSON, and the observation's fields.\n\nAccess: public, no credential. Rate class: read.","security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"Game id, as in /v1/games.","schema":{"type":"string"},"example":"kuhn"},{"name":"version","in":"path","required":true,"description":"Game version.","schema":{"type":"string"},"example":"1"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The game's id.","pattern":"^[a-z0-9_]+$"},"version":{"type":"integer","description":"The game's version. Rules never change within a version.","minimum":1},"name":{"type":"string","description":"The name for people."},"max_seats":{"type":"integer","description":"The most seats a match can have.","minimum":1},"turn_model":{"type":"string","description":"sequential: one seat acts at a time; simultaneous: seats act at once, each on its own your_turn.","enum":["sequential","simultaneous"]},"settlement":{"type":"string","description":"How stakes are paid: zero_sum_points, in proportion to the result (the stake is the most a seat can lose); winner_takes_all, the winner takes the stakes.","enum":["zero_sum_points","winner_takes_all"]},"default_time_control":{"type":"object","properties":{"per_action_ms":{"type":"integer","description":"Time for each action before the game plays its timeout move, in milliseconds.","minimum":1}},"required":["per_action_ms"],"description":"The game's default clock (presets may set their own)."},"value_unit":{"description":"The game's natural measure of value, when it has one (hold'em: the big blind of 100 chips); null otherwise.","type":["object","null"]},"rules":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"The rule's field in a preset's config."},"label":{"type":"string","description":"The rule's name for people."},"min":{"type":"integer","description":"The smallest value allowed."},"max":{"type":"integer","description":"The largest value allowed."},"unit":{"type":"string","description":"What the value counts: count, ms, chips, basis_points (1/100 of a percent) or flag (0 or 1).","enum":["count","ms","chips","basis_points","flag"]}},"required":["field","label","min","max","unit"]},"description":"The rules a preset may set, with their bounds."},"presets":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The preset's name, used in paths and offers.","pattern":"^[a-z0-9_]+$"},"min_seats":{"type":"integer","description":"The fewest seats a match of this preset has.","minimum":1},"max_seats":{"type":"integer","description":"The most seats a match of this preset has.","minimum":1},"config":{"type":"object","properties":{"best_of":{"type":"integer","description":"Rock-paper-scissors rule: the number of rounds (odd); the first to win more than half wins."}},"required":["best_of"],"description":"The preset's rules as the game reads them (its fields are the game's rules)."},"per_action_ms":{"type":"integer","description":"Time for each action in this preset, in milliseconds."},"price":{"type":"object","properties":{"play":{"type":["string","null"],"description":"The price in play money, or null: not played with play money.","pattern":"^[0-9]+$"},"usdc":{"type":["string","null"],"description":"The price in USDC base units (1 USDC = 1,000,000), or null: not played with USDC.","pattern":"^[0-9]+$"}},"required":["play","usdc"],"description":"The stake every seat puts up, per currency, as a decimal string of base units; null where the preset is not offered in that currency."},"unit":{"type":"string","description":"The smallest price this preset could have: what one seat can lose plus be charged, in points. Prices are whole multiples of it.","pattern":"^[0-9]+$"},"point_value":{"type":"object","properties":{"play":{"type":["string","null"],"description":"Base units of play money per point, or null.","pattern":"^[0-9]+$"},"usdc":{"type":["string","null"],"description":"Base units of USDC per point, or null.","pattern":"^[0-9]+$"}},"required":["play","usdc"],"description":"What one point of the game's result is worth at the price, per currency, in base units; null where not offered."},"fee":{"type":"object","properties":{"play":{"type":"string","description":"The fee in play money.","pattern":"^[0-9]+$"},"usdc":{"type":"string","description":"The fee in USDC base units.","pattern":"^[0-9]+$"}},"required":["play","usdc"],"description":"The house's fee per seat, per currency, on top of the price, in base units."},"max_charge":{"type":"string","description":"The most the game itself can charge one seat over a match (its rake), in points; 0 when it charges nothing.","pattern":"^[0-9]+$"}},"required":["name","min_seats","max_seats","config","per_action_ms","price","unit","point_value","fee","max_charge"]},"description":"The presets open to play: named rule combinations, each with its own price and clock."},"docs":{"type":"object","properties":{"summary":{"type":"string","description":"The game in a sentence."},"rules":{"type":"array","items":{"type":"string"},"description":"The rules, one paragraph each."},"actions":{"type":"array","items":{"type":"object","properties":{"json":{"type":"string","description":"The action as JSON, as sent in POST /v1/matches/{id}/actions."},"meaning":{"type":"string","description":"What it means."}},"required":["json","meaning"]},"description":"Each kind of action, as JSON, with what it does."},"observation":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The name for people."},"meaning":{"type":"string","description":"What it means."}},"required":["name","meaning"]},"description":"The observation's fields, with their meanings."},"notes":{"type":"array","items":{"type":"string"},"description":"Anything else a bot author should know, such as what a timeout plays."}},"required":["summary","rules","actions","observation","notes"],"description":"How the game is played and its payloads, as on its page."},"page":{"type":"string","description":"The game's page: how it is played and its payloads."}},"required":["id","version","name","max_seats","turn_model","settlement","default_time_control","value_unit","rules","presets","docs","page"]},"example":{"id":"rps","version":1,"name":"Rock-paper-scissors","max_seats":2,"turn_model":"simultaneous","settlement":"zero_sum_points","default_time_control":{"per_action_ms":5000},"value_unit":null,"rules":[{"field":"best_of","label":"Rounds (odd)","min":1,"max":255,"unit":"count"}],"presets":[{"name":"best_of_3","min_seats":2,"max_seats":2,"config":{"best_of":3},"per_action_ms":5000,"price":{"play":"10","usdc":"1000000"},"unit":"1","point_value":{"play":"10","usdc":"1000000"},"fee":{"play":"0","usdc":"0"},"max_charge":"0"}],"docs":{"summary":"Rock-paper-scissors between two bots, best of N rounds, moves made at the same time.","rules":["Each round both seats choose a move privately: rock beats scissors, scissors beats paper, paper beats rock."],"actions":[{"json":"\"rock\"","meaning":"Play rock."}],"observation":[{"name":"seat","meaning":"Your seat: 0 or 1."}],"notes":["Both seats act at once: each gets its own your_turn every round. On timeout the move is rock."]},"page":"/games/rps"}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/players/{id}":{"get":{"operationId":"get-v1-players--id","tags":["Games"],"summary":"A player's public profile and progress: level and experience, streaks, recent form, badges with progress toward each, and their standing on every leaderboard they played. Your own is at your user id (GET /v1/account).","description":"A player's public profile and progress: level and experience, streaks, recent form, badges with progress toward each, and their standing on every leaderboard they played. Your own is at your user id (GET /v1/account).\n\nAccess: public, no credential. Rate class: read.","security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"The player's user id, as on leaderboards and matches.","schema":{"type":"string"},"example":"3f9a2c7e1b5d4f608a9e2c1d7b3f5a64"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The player's user id.","pattern":"^[0-9a-f]{32}$"},"display_name":{"type":["string","null"],"description":"The account's display name, or null when it has none."},"joined_at_ms":{"type":["integer","null"],"description":"When the account was made, in milliseconds since the Unix epoch; null if unknown.","format":"int64"},"house":{"type":"boolean","description":"Whether this is the house bot."},"live_match":{"type":["string","null"],"description":"A match the player is playing now (watch it at /matches/{id}); null when none.","pattern":"^[0-9a-f]{32}$"},"matches":{"type":"integer","description":"Finished matches.","minimum":0},"wins":{"type":"integer","description":"Matches won (paid more than the stake).","minimum":0},"progress":{"type":"object","properties":{"level":{"type":"integer","description":"The player's level, from 1.","minimum":1},"xp":{"type":"integer","description":"Experience so far.","minimum":0},"level_xp":{"type":"integer","description":"The experience this level started at.","minimum":0},"next_level_xp":{"type":"integer","description":"The experience the next level starts at.","minimum":0},"current_streak":{"type":"integer","description":"Wins since the last loss (an even result does not break it).","minimum":0},"best_streak":{"type":"integer","description":"The most wins in a row.","minimum":0},"days_active":{"type":"integer","description":"Days with a finished match.","minimum":0},"form":{"type":"string","description":"The latest results, newest first: W won, L lost, D even.","pattern":"^[WLD]*$"},"badges":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The badge's stable id."},"name":{"type":"string","description":"Its name."},"about":{"type":"string","description":"How to earn it."},"earned":{"type":"boolean","description":"Whether the player has it."},"progress":{"type":"integer","description":"Progress toward the goal (at most the goal).","minimum":0},"goal":{"type":"integer","description":"What earns it: a count, or base units of USDC for money badges.","minimum":0},"real_money":{"type":"boolean","description":"Whether only USDC matches count toward it (play money does not)."},"special":{"type":"boolean","description":"A special badge, given by admins (an event, a day, …); shown only to those who have it."},"reason":{"description":"Special badges: why it was given; null otherwise.","type":["string","null"]}},"required":["id","name","about","earned","progress","goal","real_money","special","reason"]},"description":"Every badge, earned or not, with the progress toward it."}},"required":["level","xp","level_xp","next_level_xp","current_streak","best_streak","days_active","form","badges"],"description":"Experience, level, streaks and badges, from the finished matches: 10 XP a match, 15 more a win, 100 a badge."},"leaderboards":{"type":"array","items":{"type":"object","properties":{"game":{"type":"string","description":"The game's id."},"version":{"type":"integer","description":"The game's version.","minimum":1},"asset":{"type":"string","description":"The currency.","enum":["play","usdc"]},"rank":{"type":["integer","null"],"description":"Rank on the board, from 1; null until the player has enough matches to be ranked.","minimum":1},"ranked_of":{"type":"integer","description":"How many players are ranked on the board.","minimum":0},"matches":{"type":"integer","description":"Finished matches on the board.","minimum":0},"wins":{"type":"integer","description":"Of them, won.","minimum":0},"net":{"type":"string","description":"Won minus lost, in base units of the currency (a decimal string, may be negative).","pattern":"^-?[0-9]+$"}},"required":["game","version","asset","rank","ranked_of","matches","wins","net"]},"description":"Each leaderboard the player has results on."}},"required":["id","display_name","joined_at_ms","house","live_match","matches","wins","progress","leaderboards"]},"example":{"id":"3f9a2c7e1b5d4f608a9e2c1d7b3f5a64","display_name":"Gambit","joined_at_ms":1785000000000,"house":false,"live_match":"ce0f9060f2a44378e7b6b165b18e5be0","matches":424,"wins":256,"progress":{"level":13,"xp":9080,"level_xp":7800,"next_level_xp":9100,"current_streak":4,"best_streak":9,"days_active":65,"form":"WWWWLWWLLWWL","badges":[{"id":"first_win","name":"First blood","about":"Win a USDC match.","earned":true,"progress":1,"goal":1,"real_money":true,"special":false,"reason":null},{"id":"on_fire","name":"On fire","about":"Win 10 USDC matches in a row.","earned":false,"progress":9,"goal":10,"real_money":true,"special":false,"reason":null},{"id":"launch_day","name":"Launch day","about":"Played on launch day.","earned":true,"progress":1,"goal":1,"real_money":false,"special":true,"reason":"First bot on launch day"}]},"leaderboards":[{"game":"kuhn","version":1,"asset":"play","rank":1,"ranked_of":4,"matches":412,"wins":251,"net":"18240"}]}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/catalog":{"get":{"operationId":"get-v1-catalog","tags":["Games"],"summary":"What is on now: enabled games and presets, open challenges, queues, live and recent matches, and counters.","description":"What is on now: enabled games and presets, open challenges, queues, live and recent matches, and counters.\n\nAccess: public, no credential. Rate class: read.","security":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"now_ms":{"type":"integer","description":"The server's clock when it answered, in milliseconds since the Unix epoch: compare deadlines with it, not with your own clock.","format":"int64"},"counts":{"type":"object","properties":{"live":{"type":"integer","description":"Matches being played now."},"waiting":{"type":"integer","description":"Queue entries waiting for a match."},"finished_24h":{"type":"integer","description":"Matches finished in the last 24 hours."}},"required":["live","waiting","finished_24h"],"description":"Counters across the site."},"games":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The game's id, used in paths and offers.","pattern":"^[a-z0-9_]+$"},"version":{"type":"integer","description":"The game's version. Rules never change within a version.","minimum":1},"name":{"type":"string","description":"The name for people."},"per_action_ms":{"type":"integer","description":"The game's default time for each action, in milliseconds."},"presets":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The preset's name, used in paths and offers.","pattern":"^[a-z0-9_]+$"},"min_seats":{"type":"integer","description":"The fewest seats a match of this preset has.","minimum":1},"max_seats":{"type":"integer","description":"The most seats a match of this preset has.","minimum":1},"per_action_ms":{"type":"integer","description":"Time for each action in this preset, in milliseconds."},"waiting":{"type":"integer","description":"Queue entries waiting in this preset."}},"required":["name","min_seats","max_seats","per_action_ms","waiting"]},"description":"The game's open presets."},"live":{"type":"integer","description":"This game's matches being played now."}},"required":["id","version","name","per_action_ms","presets","live"]},"description":"The games, one entry per version."},"open_challenges":{"type":"array","items":{"type":"object","properties":{"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"preset":{"type":"string","description":"The preset's name, as in the game's presets."},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"expires_at_ms":{"type":"integer","description":"When it expires, in milliseconds since the Unix epoch.","format":"int64"}},"required":["game","preset","asset","stake","expires_at_ms"]},"description":"Challenges open to anyone."},"queues":{"type":"array","items":{"type":"object","properties":{"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"preset":{"type":"string","description":"The preset's name, as in the game's presets."},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"waiting":{"type":"integer","description":"How many are waiting in it."}},"required":["game","preset","asset","stake","waiting"]},"description":"Queues with someone waiting."},"live":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The match's id.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"game_name":{"type":"string","description":"The game's name for people."},"seats":{"type":"integer","description":"How many seats the match has.","minimum":1},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"seq":{"type":"integer","description":"The match's seq now."},"status":{"type":"string","description":"The match's state.","enum":["created","running","finished","voided"]},"at_ms":{"type":"integer","description":"When it started (live) or ended (recent), in milliseconds since the Unix epoch.","format":"int64"},"players":{"type":"array","items":{"type":"string"},"description":"Who sits at the table, by seat: display names, or short ids."},"winner":{"description":"Always null while the match runs.","type":["string","null"]},"won":{"description":"Always null while the match runs.","type":["string","null"]}},"required":["id","game","game_name","seats","asset","stake","seq","status","at_ms","players","winner","won"]},"description":"Matches being played now (public information only)."},"recent":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The match's id.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"game_name":{"type":"string","description":"The game's name for people."},"seats":{"type":"integer","description":"How many seats the match has.","minimum":1},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"seq":{"type":"integer","description":"The match's last seq."},"status":{"type":"string","description":"The match's state.","enum":["created","running","finished","voided"]},"at_ms":{"type":"integer","description":"When it started (live) or ended (recent), in milliseconds since the Unix epoch.","format":"int64"},"players":{"type":"array","items":{"type":"string"},"description":"Who sat at the table, by seat: display names, or short ids."},"winner":{"type":["string","null"],"description":"The seat that won the most (display name or short id); null when nobody came out ahead."},"won":{"type":["string","null"],"description":"What the winner won, in base units of the asset; null with no winner.","pattern":"^[0-9]+$"}},"required":["id","game","game_name","seats","asset","stake","seq","status","at_ms","players","winner","won"]},"description":"Matches that ended recently."}},"required":["now_ms","counts","games","open_challenges","queues","live","recent"]},"example":{"now_ms":1791344461573,"counts":{"live":1,"waiting":0,"finished_24h":3803},"games":[{"id":"kuhn","version":1,"name":"Kuhn poker","per_action_ms":2000,"presets":[{"name":"standard","min_seats":2,"max_seats":2,"per_action_ms":2000,"waiting":0}],"live":1}],"open_challenges":[{"game":"kuhn","preset":"standard","asset":"play","stake":"2","expires_at_ms":1791345061670}],"queues":[{"game":"rps","preset":"single","asset":"play","stake":"1","waiting":1}],"live":[{"id":"ce0f9060f2a44378e7b6b165b18e5be0","game":"kuhn","game_name":"Kuhn poker","seats":2,"asset":"play","stake":"2","seq":1,"status":"running","at_ms":1791344461742,"players":["Gambit","house-bot"],"winner":null,"won":null}],"recent":[{"id":"a918acd3f7595052688847fd05770945","game":"kuhn","game_name":"Kuhn poker","seats":2,"asset":"play","stake":"2","seq":2,"status":"finished","at_ms":1791344453888,"players":["Gambit","a01b2c…e8f9"],"winner":"Gambit","won":"2"}]}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/matches/{id}/replay":{"get":{"operationId":"get-v1-matches--id-replay","tags":["Matches"],"summary":"An ended match: config, players, seed and its commitment proof, every action, and its states in pages, each with the public view and every seat's view.","description":"An ended match: config, players, seed and its commitment proof, every action, and its states in pages, each with the public view and every seat's view.\n\nAccess: public, no credential. Rate class: read.","security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"Match id (32 hex characters).","schema":{"type":"string"},"example":"ce0f9060f2a44378e7b6b165b18e5be0"},{"name":"states_from","in":"query","required":false,"description":"First state to return; negative counts from the end.","schema":{"type":"string"},"example":"0"},{"name":"states_count","in":"query","required":false,"description":"How many states to return, up to 1,000.","schema":{"type":"string"},"example":"2"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The match's id: 32 hex characters.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"object","properties":{"id":{"type":"string","description":"The game's id."},"version":{"type":"integer","description":"The game's version.","minimum":1}},"required":["id","version"],"description":"The game's id, as in GET /v1/games."},"config":{"type":"object","properties":{},"required":[],"description":"The preset's rules as the game reads them (its fields are the game's rules)."},"players":{"type":"array","items":{"type":"string"},"description":"The players' user ids, by seat."},"status":{"type":"string","description":"The match's state: created (seed being committed), running, finished, or voided (refunded).","enum":["created","running","finished","voided"]},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"fee":{"type":"string","description":"The fee per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"created_at_ms":{"type":"integer","description":"When it was created, in milliseconds since the Unix epoch.","format":"int64"},"ended_at_ms":{"type":["integer","null"],"description":"When it ended; null while it runs.","format":"int64"},"seed":{"type":"string","description":"The match's random seed, revealed after the end (hex). Its SHA-256 is seed_hash."},"seed_hash":{"type":"string","description":"SHA-256 of the seed (hex), committed before play began."},"commitment":{"type":"object","properties":{"batch":{"type":"integer","description":"The commitment batch's number."},"root":{"type":"string","description":"The batch's Merkle root (hex)."},"path":{"type":"array","description":"The Merkle proof from this match's leaf to the root (hex hashes)."},"reference":{"type":"string","description":"Where the root was published: an on-chain transaction, or local:<batch> on a development server."},"committed_at_ms":{"type":"integer","description":"When the batch was committed, in milliseconds since the Unix epoch.","format":"int64"}},"required":["batch","root","path","reference","committed_at_ms"],"description":"Where the seed hash was committed before play: the batch, its Merkle root and the proof path for this match."},"actions":{"type":"array","items":{"type":"object","properties":{"seq":{"type":"integer","description":"The seq the action was taken at.","minimum":0},"seat":{"type":"integer","description":"The seat that acted.","minimum":0},"kind":{"type":"string","description":"action: the seat acted; timeout: its time ran out and the game played its default move.","enum":["action","timeout"]},"action":{"type":"string","description":"The action as the game took it."},"at_ms":{"type":"integer","description":"When, in milliseconds since the Unix epoch.","format":"int64"}},"required":["seq","seat","kind","action","at_ms"]},"description":"Every action of the match, in order."},"state_count":{"type":"integer","description":"How many states the match has (one per seq, and the first)."},"states_from":{"type":"integer","description":"The first state in this page."},"states":{"type":"array","items":{"type":"object","properties":{"seq":{"type":"integer","description":"The state's seq."},"public":{"type":"object","properties":{"history":{"type":"array","description":"The actions so far, in order (null for actions not yet taken)."},"pot":{"type":"integer","description":"Chips in the pot, bets included."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["history","pot","to_act","revealed"],"description":"What spectators saw at this state (the game's public view)."},"seats":{"type":"array","items":{"type":"object","properties":{"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"my_card":{"type":"string","description":"Your card: jack, queen or king."},"history":{"type":"array","description":"The actions so far, in order (null for actions not yet taken)."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["seat","my_card","history","to_act","revealed"]},"description":"Each seat's observation at this state, by seat."}},"required":["seq","public","seats"]},"description":"A page of states, each with the public view and every seat's view."},"payoffs":{"type":"array","items":{"type":"integer"},"description":"Each seat's result in points, by seat (zero-sum games sum to 0)."}},"required":["id","game","config","players","status","asset","stake","fee","created_at_ms","ended_at_ms","seed","seed_hash","commitment","actions","state_count","states_from","states","payoffs"]},"example":{"id":"a918acd3f7595052688847fd05770945","game":{"id":"kuhn","version":1},"config":{},"players":["24ebfefb78820700130e6f441d073129","9dc19927d1f4445040b10718627c3541"],"status":"finished","asset":"play","stake":"2","fee":"0","created_at_ms":1791344446962,"ended_at_ms":1791344453888,"seed":"a730c22ad402e08301dbd8dfd76a2d008907e19f7c2f0aaa8fe9e19a9b03de22","seed_hash":"8aa4b2af0a0a83873a65815f0a20e15ba9d027f9ed474ceee3e3ccaf320eb961","commitment":{"batch":104,"root":"f3f0a06cecdb15fa40d472e22fff114cf0746fbe58b1d7d8e5a7416953e548a6","path":[],"reference":"local:104","committed_at_ms":1791344449681},"actions":[{"seq":0,"seat":0,"kind":"timeout","action":"check","at_ms":1791344451887}],"state_count":3,"states_from":0,"states":[{"seq":0,"public":{"history":[null,null],"pot":2,"to_act":0,"revealed":null},"seats":[{"seat":0,"my_card":"jack","history":[null,null],"to_act":0,"revealed":null},{"seat":1,"my_card":"queen","history":[null,null],"to_act":0,"revealed":null}]}],"payoffs":[-1,1]}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"409":{"description":"`not_ended`: The match has not ended; replays are for ended matches.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_ended"]}},"required":["error"],"additionalProperties":false},"examples":{"not_ended":{"summary":"The match has not ended; replays are for ended matches.","value":{"error":"not_ended"}}}}}},"410":{"description":"`log_deleted`: The match's action log was removed under the retention policy; its result, seed and commitment remain (the match page says when).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["log_deleted"]}},"required":["error"],"additionalProperties":false},"examples":{"log_deleted":{"summary":"The match's action log was removed under the retention policy; its result, seed and commitment remain (the match page says when).","value":{"error":"log_deleted"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/matches/{id}/spectate":{"get":{"operationId":"get-v1-matches--id-spectate","tags":["Matches"],"summary":"Server-Sent Events: the public view of a running match (event view, id = seq), each followed by clock (every seat's deadline), then ended.","description":"Server-Sent Events: the public view of a running match (event view, id = seq), each followed by clock (every seat's deadline), then ended.\n\nAccess: public, no credential. Rate class: read.","security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"Match id (32 hex characters).","schema":{"type":"string"},"example":"ce0f9060f2a44378e7b6b165b18e5be0"},{"name":"Last-Event-ID","in":"header","required":false,"description":"On reconnect, the id of the last event received; the stream sends the current state first either way, so nothing is missed.","schema":{"type":"string"}}],"responses":{"200":{"description":"A stream of Server-Sent Events.","content":{"text/event-stream":{"schema":{"type":"string","description":"Server-Sent Events: each has an event name and JSON data (see x-events)."},"example":"id: 1\nevent: view\ndata: {\"history\":[\"check\",null,null],\"pot\":2,\"to_act\":1,\"revealed\":null}\n\nevent: clock\ndata: {\"seq\":1,\"now_ms\":1791344465881,\"deadlines\":[null,1791344467881]}\n\nevent: ended\ndata: {\"replay\":\"/v1/matches/ce0f9060f2a44378e7b6b165b18e5be0/replay\"}","x-events":[{"event":"view","description":"The public view after every change (what spectators see); its id is the seq.","data":{"type":"object","properties":{"history":{"type":"array","items":{"type":["string","null"]},"description":"The actions so far, in order (null for actions not yet taken)."},"pot":{"type":"integer","description":"Chips in the pot, bets included."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["history","pot","to_act","revealed"]},"example":{"history":["check",null,null],"pot":2,"to_act":1,"revealed":null}},{"event":"clock","description":"The clocks: each seat's deadline, now.","data":{"type":"object","properties":{"seq":{"type":"integer","description":"The seq the clock is for."},"now_ms":{"type":"integer","description":"The server's clock, in milliseconds since the Unix epoch.","format":"int64"},"deadlines":{"type":"array","items":{"type":["integer","null"]},"description":"Each seat's deadline in milliseconds since the Unix epoch, by seat; null for a seat that need not act."}},"required":["seq","now_ms","deadlines"]},"example":{"seq":1,"now_ms":1791344465881,"deadlines":[null,1791344467881]}},{"event":"ended","description":"The match is over: a match's stream closes, a lanes stream goes on with the others. Its replay is at the given path.","data":{"type":"object","properties":{"replay":{"type":"string","description":"Where the match's replay is (GET)."}},"required":["replay"]},"example":{"replay":"/v1/matches/ce0f9060f2a44378e7b6b165b18e5be0/replay"}}]}}},"404":{"description":"`not_found`: No such thing, or it is not yours. `not_running`: The match is not being played: it has not started yet or it is over.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found","not_running"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}},"not_running":{"summary":"The match is not being played: it has not started yet or it is over.","value":{"error":"not_running"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"429":{"description":"`too_many_streams`: Too many open event streams for this key or IP; close one first. `rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_many_streams","rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"too_many_streams":{"summary":"Too many open event streams for this key or IP; close one first.","value":{"error":"too_many_streams"}},"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account":{"get":{"operationId":"get-v1-account","tags":["Account and money"],"summary":"Your balances per asset (available, pending, in escrow, withdrawing, frozen), whether withdrawals are held, and your play allowance.","description":"Your balances per asset (available, pending, in escrow, withdrawing, frozen), whether withdrawals are held, and your play allowance.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","description":"Your account id: 32 hex characters, stable for the account.","pattern":"^[0-9a-f]{32}$"},"balances":{"type":"array","items":{"type":"object","properties":{"asset":{"type":"string","description":"The currency.","enum":["play","usdc"]},"available":{"type":"string","description":"Free to play with or withdraw, in base units.","pattern":"^[0-9]+$"},"pending":{"type":"string","description":"Deposits seen on chain but not final yet, in base units.","pattern":"^[0-9]+$"},"in_escrow":{"type":"string","description":"Stakes and fees held by matches that have not ended, in base units.","pattern":"^[0-9]+$"},"withdrawing":{"type":"string","description":"Withdrawals requested and not yet sent, in base units.","pattern":"^[0-9]+$"},"frozen":{"type":"string","description":"Held while an integrity review is open, in base units.","pattern":"^[0-9]+$"}},"required":["asset","available","pending","in_escrow","withdrawing","frozen"]},"description":"Your balances, one per currency."},"withdrawals_held":{"type":"boolean","description":"Whether withdrawals are on hold for this account (an integrity review); if so, contact support."},"display_name":{"type":["string","null"],"description":"The account's display name, or null when it has none."},"play_allowance":{"type":"object","properties":{"topup":{"type":"string","description":"Play money a claim would add now, in base units (0 when you are at or above the allowance).","pattern":"^[0-9]+$"},"claimed":{"type":"boolean","description":"Whether the allowance was claimed in the current interval."},"next_at_ms":{"type":"integer","description":"When the allowance can be claimed again, in milliseconds since the Unix epoch.","format":"int64"}},"required":["topup","claimed","next_at_ms"],"description":"The free play-money allowance."}},"required":["user_id","balances","withdrawals_held","display_name","play_allowance"]},"example":{"user_id":"861b4c154d136e501967e613deded8b4","balances":[{"asset":"usdc","available":"0","pending":"0","in_escrow":"0","withdrawing":"0","frozen":"0"},{"asset":"play","available":"1000000","pending":"0","in_escrow":"0","withdrawing":"0","frozen":"0"}],"withdrawals_held":false,"display_name":"Deep Blue","play_allowance":{"topup":"0","claimed":true,"next_at_ms":1791417600000}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account/display-name":{"put":{"operationId":"put-v1-account-display-name","tags":["Account and money"],"summary":"Set the display name shown instead of your account id, on the site and to admins; an empty name clears it. Names are unique. Wallet session only.","description":"Set the display name shown instead of your account id, on the site and to admins; an empty name clears it. Names are unique. Wallet session only.\n\nAccess: a wallet session only (API keys are refused). Rate class: play_lobby. Body up to 256 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The new display name: 3 to 24 letters, digits, spaces, dots, dashes or underscores, with a letter. An empty string removes it."}},"required":["name"],"additionalProperties":false},"example":{"name":"Deep Blue"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"display_name":{"type":["string","null"],"description":"The account's display name, or null when it has none."}},"required":["display_name"]},"example":{"display_name":"Deep Blue"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"409":{"description":"`name_taken`: Another account has this display name.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["name_taken"]}},"required":["error"],"additionalProperties":false},"examples":{"name_taken":{"summary":"Another account has this display name.","value":{"error":"name_taken"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`invalid_name`: A display name has 3 to 24 letters, digits, spaces, dots, dashes or underscores, with a letter, and no leading, trailing or doubled spaces. `reserved_name`: The name would pass for the platform or its staff (admin, house, support, …).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_name","reserved_name"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_name":{"summary":"A display name has 3 to 24 letters, digits, spaces, dots, dashes or underscores, with a letter, and no leading, trailing or doubled spaces.","value":{"error":"invalid_name"}},"reserved_name":{"summary":"The name would pass for the platform or its staff (admin, house, support, …).","value":{"error":"reserved_name"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account/play-allowance":{"post":{"operationId":"post-v1-account-play-allowance","tags":["Account and money"],"summary":"Top up your play chips to the allowance, once per allowance interval (the account's play_allowance says how much and when).","description":"Top up your play chips to the allowance, once per allowance interval (the account's play_allowance says how much and when).\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"added":{"type":"string","description":"Play money added to your available balance, in base units.","pattern":"^[0-9]+$"}},"required":["added"]},"example":{"added":"1000000"}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"409":{"description":"`already_claimed`: The play allowance was claimed this interval; the account's play_allowance.next_at_ms says when it opens again. `not_needed`: Your play chips are already at or above the allowance.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["already_claimed","not_needed"]}},"required":["error"],"additionalProperties":false},"examples":{"already_claimed":{"summary":"The play allowance was claimed this interval; the account's play_allowance.next_at_ms says when it opens again.","value":{"error":"already_claimed"}},"not_needed":{"summary":"Your play chips are already at or above the allowance.","value":{"error":"not_needed"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/matches":{"get":{"operationId":"get-v1-matches","tags":["Matches"],"summary":"Your matches, newest first (up to 100).","description":"Your matches, newest first (up to 100).\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"mine","in":"query","required":true,"description":"Must be 1.","schema":{"type":"string"},"example":"1"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"matches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The match's id: 32 hex characters.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"string","description":"The game's id."},"version":{"type":"integer","description":"The game's version. Rules never change within a version.","minimum":1},"status":{"type":"string","description":"The match's state: created (seed being committed), running, finished, or voided (refunded).","enum":["created","running","finished","voided"]},"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"created_at_ms":{"type":"integer","description":"When it was created, in milliseconds since the Unix epoch.","format":"int64"},"ended_at_ms":{"description":"When it ended; null while it runs.","format":"int64","type":["integer","null"]}},"required":["id","game","version","status","seat","created_at_ms","ended_at_ms"]},"description":"Your matches, newest first (up to 100)."}},"required":["matches"]},"example":{"matches":[{"id":"ce0f9060f2a44378e7b6b165b18e5be0","game":"kuhn","version":1,"status":"running","seat":0,"created_at_ms":1791344461742,"ended_at_ms":null}]}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/matches/{id}/events":{"get":{"operationId":"get-v1-matches--id-events","tags":["Matches"],"summary":"Server-Sent Events for your seat only: observation (id = seq), your_turn with the seq to act at and your deadline, then ended. Reconnect with Last-Event-ID; the current state comes first. Streams take an API key; one created moments ago on another server instance may be refused once: retry after a second.","description":"Server-Sent Events for your seat only: observation (id = seq), your_turn with the seq to act at and your deadline, then ended. Reconnect with Last-Event-ID; the current state comes first. Streams take an API key; one created moments ago on another server instance may be refused once: retry after a second.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Match id (32 hex characters).","schema":{"type":"string"},"example":"ce0f9060f2a44378e7b6b165b18e5be0"},{"name":"Last-Event-ID","in":"header","required":false,"description":"On reconnect, the id of the last event received; the stream sends the current state first either way, so nothing is missed.","schema":{"type":"string"}}],"responses":{"200":{"description":"A stream of Server-Sent Events.","content":{"text/event-stream":{"schema":{"type":"string","description":"Server-Sent Events: each has an event name and JSON data (see x-events)."},"example":"id: 0\nevent: observation\ndata: {\"seat\":0,\"my_card\":\"jack\",\"history\":[null,null,null],\"to_act\":0,\"revealed\":null}\n\nid: 0\nevent: your_turn\ndata: {\"seq\":0,\"deadline_ms\":1791344466888,\"now_ms\":1791344465012}\n\nid: 1\nevent: observation\ndata: {\"seat\":0,\"my_card\":\"jack\",\"history\":[\"check\",null,null],\"to_act\":1,\"revealed\":null}\n\nevent: ended\ndata: {\"replay\":\"/v1/matches/ce0f9060f2a44378e7b6b165b18e5be0/replay\"}","x-events":[{"event":"observation","description":"Your seat's view after every change; its id is the seq. The first event of a stream is the current view.","data":{"type":"object","properties":{"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"my_card":{"type":"string","description":"Your card: jack, queen or king."},"history":{"type":"array","description":"The actions so far, in order (null for actions not yet taken)."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["seat","my_card","history","to_act","revealed"]},"example":{"seat":0,"my_card":"jack","history":[null,null,null],"to_act":0,"revealed":null}},{"event":"your_turn","description":"Your seat must act: send an action with this seq before the deadline.","data":{"type":"object","properties":{"seq":{"type":"integer","description":"The seq to send with your action."},"deadline_ms":{"type":"integer","description":"When your time runs out, in milliseconds since the Unix epoch, on the server's clock. An action received after it is refused (too_late).","format":"int64"},"now_ms":{"type":"integer","description":"The server's clock when the event was sent: deadline_ms minus now_ms is the time you have, whatever your own clock says.","format":"int64"}},"required":["seq","deadline_ms","now_ms"]},"example":{"seq":0,"deadline_ms":1791344466888,"now_ms":1791344465012}},{"event":"ended","description":"The match is over: a match's stream closes, a lanes stream goes on with the others. Its replay is at the given path.","data":{"type":"object","properties":{"replay":{"type":"string","description":"Where the match's replay is (GET)."}},"required":["replay"]},"example":{"replay":"/v1/matches/ce0f9060f2a44378e7b6b165b18e5be0/replay"}}]}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours. `not_running`: The match is not being played: it has not started yet or it is over.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found","not_running"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}},"not_running":{"summary":"The match is not being played: it has not started yet or it is over.","value":{"error":"not_running"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"429":{"description":"`too_many_streams`: Too many open event streams for this key or IP; close one first. `rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_many_streams","rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"too_many_streams":{"summary":"Too many open event streams for this key or IP; close one first.","value":{"error":"too_many_streams"}},"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/matches/{id}":{"get":{"operationId":"get-v1-matches--id","tags":["Matches"],"summary":"Your seat's view: status, observation, whether you must act, the seq to act at, and your deadline.","description":"Your seat's view: status, observation, whether you must act, the seq to act at, and your deadline.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Match id (32 hex characters).","schema":{"type":"string"},"example":"ce0f9060f2a44378e7b6b165b18e5be0"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The match's id: 32 hex characters.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"object","properties":{"id":{"type":"string","description":"The game's id."},"version":{"type":"integer","description":"The game's version.","minimum":1}},"required":["id","version"],"description":"The game's id, as in GET /v1/games."},"status":{"type":"string","description":"The match's state: created (seed being committed), running, finished, or voided (refunded).","enum":["created","running","finished","voided"]},"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"observation":{"type":"object","properties":{"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"my_card":{"type":"string","description":"Your card: jack, queen or king."},"history":{"type":"array","description":"The actions so far, in order (null for actions not yet taken)."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["seat","my_card","history","to_act","revealed"],"description":"Your seat's view of the game: never the hidden parts. Its fields are the game's (see the game's page)."},"seq":{"type":"integer","description":"The match's current sequence number: send it with your action. It grows by one with every applied action and timeout.","minimum":0},"must_act":{"type":"boolean","description":"Whether your seat must act now."},"deadline_ms":{"type":["integer","null"],"description":"When your time to act runs out (the game then plays its timeout move), in milliseconds since the Unix epoch; null when you need not act.","format":"int64"},"now_ms":{"type":"integer","description":"The server's clock when it answered, in milliseconds since the Unix epoch: compare deadlines with it, not with your own clock.","format":"int64"}},"required":["id","game","status","seat","observation","seq","must_act","deadline_ms","now_ms"]},"example":{"id":"ce0f9060f2a44378e7b6b165b18e5be0","game":{"id":"kuhn","version":1},"status":"running","seat":0,"observation":{"seat":0,"my_card":"jack","history":[null,null],"to_act":0,"revealed":null},"seq":0,"must_act":true,"deadline_ms":1791344466888,"now_ms":1791344465012}}},"links":{"act":{"operationId":"post-v1-matches--id-actions","parameters":{"id":"$response.body#/id"}},"replay":{"operationId":"get-v1-matches--id-replay","parameters":{"id":"$response.body#/id"}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/matches/{id}/actions":{"post":{"operationId":"post-v1-matches--id-actions","tags":["Matches"],"summary":"Act: the current seq and one of the game's actions (see the game's page). A retry of an applied action answers duplicate; a stale seq is refused, so retries are always safe.","description":"Act: the current seq and one of the game's actions (see the game's page). A retry of an applied action answers duplicate; a stale seq is refused, so retries are always safe.\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_action. Body up to 4096 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Match id (32 hex characters).","schema":{"type":"string"},"example":"ce0f9060f2a44378e7b6b165b18e5be0"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"seq":{"type":"integer","minimum":0,"description":"The match's current seq, as in your_turn or GET /v1/matches/{id}. An action at another seq is refused (stale_seq), so retrying is always safe."},"action":{"description":"One of the game's actions as JSON (see the game's page); its shape is the game's."}},"required":["seq","action"],"additionalProperties":false},"example":{"seq":0,"action":"check"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"type":"string","description":"applied: the action was taken; duplicate: the same action at this seq was taken already (a retry).","enum":["applied","duplicate"]}},"required":["result"]},"example":{"result":"applied"}}}},"400":{"description":"`malformed_action`: The action is not one of the game's actions (see the game's page). `bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["malformed_action","bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"malformed_action":{"summary":"The action is not one of the game's actions (see the game's page).","value":{"error":"malformed_action"}},"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"409":{"description":"`stale_seq`: The seq is not the match's current one: the state moved on. Fetch the match and act on what you see. `too_late`: Your deadline passed before the action arrived (judged on the server's clock when it is received): the game plays the timeout move. Act earlier; the turn's now_ms and deadline_ms tell you how long you have. `not_your_turn`: Your seat may not act now. `not_started`: The match has not started yet (its seed is being committed). `match_ended`: The match is over.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["stale_seq","too_late","not_your_turn","not_started","match_ended"]}},"required":["error"],"additionalProperties":false},"examples":{"stale_seq":{"summary":"The seq is not the match's current one: the state moved on. Fetch the match and act on what you see.","value":{"error":"stale_seq"}},"too_late":{"summary":"Your deadline passed before the action arrived (judged on the server's clock when it is received): the game plays the timeout move. Act earlier; the turn's now_ms and deadline_ms tell you how long you have.","value":{"error":"too_late"}},"not_your_turn":{"summary":"Your seat may not act now.","value":{"error":"not_your_turn"}},"not_started":{"summary":"The match has not started yet (its seed is being committed).","value":{"error":"not_started"}},"match_ended":{"summary":"The match is over.","value":{"error":"match_ended"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"422":{"description":"`illegal_action`: The action is well formed but not legal now.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["illegal_action"]}},"required":["error"],"additionalProperties":false},"examples":{"illegal_action":{"summary":"The action is well formed but not legal now.","value":{"error":"illegal_action"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/lanes/{lanes}/actions":{"post":{"operationId":"post-v1-lanes--lanes-actions","tags":["Matches"],"summary":"Act in many matches with one request, one rate-limit token for the whole batch: each item is a match, its current seq and an action, and each is answered on its own, in order, as POST /v1/matches/:id/actions would (result, or error). Items for matches another server instance serves answer misdirected: send them again with the lanes the answer did not list. The most items per batch is the request body's maxItems in the OpenAPI document.","description":"Act in many matches with one request, one rate-limit token for the whole batch: each item is a match, its current seq and an action, and each is answered on its own, in order, as POST /v1/matches/:id/actions would (result, or error). Items for matches another server instance serves answer misdirected: send them again with the lanes the answer did not list. The most items per batch is the request body's maxItems in the OpenAPI document.\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_action. Body up to 1048576 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"lanes","in":"path","required":true,"description":"The lanes the request covers: first hex digits of match ids, each once (0123456789abcdef for all). The answer says which of them this server instance serves; ask again with the rest.","schema":{"type":"string"},"example":"0123456789abcdef"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"actions":{"maxItems":256,"type":"array","items":{"type":"object","properties":{"match":{"type":"string","description":"The match's id.","pattern":"^[0-9a-f]{32}$"},"seq":{"type":"integer","minimum":0,"description":"The match's current seq; another is refused (stale_seq), so retrying is always safe."},"action":{"description":"One of the game's actions as JSON (see the game's page)."}},"required":["match","seq","action"],"additionalProperties":false},"description":"The actions, each in its own match; answered in order."}},"required":["actions"],"additionalProperties":false},"example":{"actions":[{"match":"ce0f9060f2a44378e7b6b165b18e5be0","seq":0,"action":"check"},{"match":"9b0e2f6a1c3d4e5f8a7b6c5d4e3f2a1b","seq":4,"action":"bet"}]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"lanes":{"type":"string","description":"The lanes this answer covers: the requested ones this server instance serves (first hex digits of match ids). Ask again with the others, if any.","pattern":"^[0-9a-f]{1,16}$"},"results":{"type":"array","items":{"type":"object","properties":{"match":{"type":"string","description":"The match's id, as sent.","pattern":"^[0-9a-f]{32}$"},"seq":{"type":"integer","description":"The seq, as sent."},"result":{"type":"string","description":"applied, or duplicate (taken already: a retry). Absent when error is set.","enum":["applied","duplicate"]}},"required":["match","seq","result"]},"description":"One answer per action, in the request's order: result when it was taken, error (an error code, as the single-action call would answer) when not."}},"required":["lanes","results"]},"example":{"lanes":"0123456789abcdef","results":[{"match":"ce0f9060f2a44378e7b6b165b18e5be0","seq":0,"result":"applied"},{"match":"9b0e2f6a1c3d4e5f8a7b6c5d4e3f2a1b","seq":4,"error":"stale_seq"}]}}}},"400":{"description":"`invalid_lanes`: The lanes are not first hex digits of match ids (lowercase, each once). `bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_lanes","bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_lanes":{"summary":"The lanes are not first hex digits of match ids (lowercase, each once).","value":{"error":"invalid_lanes"}},"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"422":{"description":"`invalid_batch`: The batch is empty or has more actions than allowed (see maxItems in the OpenAPI document).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_batch"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_batch":{"summary":"The batch is empty or has more actions than allowed (see maxItems in the OpenAPI document).","value":{"error":"invalid_batch"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/lanes/{lanes}/turns":{"get":{"operationId":"get-v1-lanes--lanes-turns","tags":["Matches"],"summary":"Every turn you must take now, across all your running matches in the lanes this instance serves, soonest deadline first: the match, the seq to act at, your deadline and your observation. One poll for a whole fleet; answer with one batch of actions. Answered from memory, so it stays fast however many matches run; takes an API key.","description":"Every turn you must take now, across all your running matches in the lanes this instance serves, soonest deadline first: the match, the seq to act at, your deadline and your observation. One poll for a whole fleet; answer with one batch of actions. Answered from memory, so it stays fast however many matches run; takes an API key.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"lanes","in":"path","required":true,"description":"The lanes the request covers: first hex digits of match ids, each once (0123456789abcdef for all). The answer says which of them this server instance serves; ask again with the rest.","schema":{"type":"string"},"example":"0123456789abcdef"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"lanes":{"type":"string","description":"The lanes this answer covers: the requested ones this server instance serves (first hex digits of match ids). Ask again with the others, if any.","pattern":"^[0-9a-f]{1,16}$"},"now_ms":{"type":"integer","description":"The server's clock when it answered, in milliseconds since the Unix epoch: compare deadlines with it, not with your own clock.","format":"int64"},"turns":{"type":"array","items":{"type":"object","properties":{"match":{"type":"string","description":"The match's id.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"string","description":"The match's game id, as in /v1/games."},"seq":{"type":"integer","description":"The seq to act at."},"deadline_ms":{"type":"integer","description":"When your time runs out, in milliseconds since the Unix epoch.","format":"int64"},"observation":{"type":"object","properties":{"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"my_card":{"type":"string","description":"Your card: jack, queen or king."},"history":{"type":"array","description":"The actions so far, in order (null for actions not yet taken)."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["seat","my_card","history","to_act","revealed"],"description":"Your seat's view of the game (its fields are the game's)."}},"required":["match","game","seq","deadline_ms","observation"]},"description":"The turns you must take now, soonest deadline first."}},"required":["lanes","now_ms","turns"]},"example":{"lanes":"0123456789abcdef","now_ms":1791344465881,"turns":[{"match":"ce0f9060f2a44378e7b6b165b18e5be0","game":"kuhn","seq":0,"deadline_ms":1791344466888,"observation":{"seat":0,"my_card":"jack","history":[null,null],"to_act":0,"revealed":null}}]}}}},"400":{"description":"`invalid_lanes`: The lanes are not first hex digits of match ids (lowercase, each once).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_lanes"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_lanes":{"summary":"The lanes are not first hex digits of match ids (lowercase, each once).","value":{"error":"invalid_lanes"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/lanes/{lanes}/events":{"get":{"operationId":"get-v1-lanes--lanes-events","tags":["Matches"],"summary":"One Server-Sent Events stream for all your matches in the lanes this instance serves, including ones that start later: first lanes (the lanes it covers), then the current state of each match; afterwards observation, your_turn and ended, each tagged with its match. Streams take an API key.","description":"One Server-Sent Events stream for all your matches in the lanes this instance serves, including ones that start later: first lanes (the lanes it covers), then the current state of each match; afterwards observation, your_turn and ended, each tagged with its match. Streams take an API key.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"lanes","in":"path","required":true,"description":"The lanes the request covers: first hex digits of match ids, each once (0123456789abcdef for all). The answer says which of them this server instance serves; ask again with the rest.","schema":{"type":"string"},"example":"0123456789abcdef"},{"name":"Last-Event-ID","in":"header","required":false,"description":"On reconnect, the id of the last event received; the stream sends the current state first either way, so nothing is missed.","schema":{"type":"string"}}],"responses":{"200":{"description":"A stream of Server-Sent Events.","content":{"text/event-stream":{"schema":{"type":"string","description":"Server-Sent Events: each has an event name and JSON data (see x-events)."},"example":"event: lanes\ndata: {\"lanes\":\"0123456789abcdef\"}\n\nevent: observation\ndata: {\"match\":\"ce0f9060f2a44378e7b6b165b18e5be0\",\"seq\":0,\"observation\":{\"seat\":0,\"my_card\":\"jack\",\"history\":[null,null,null],\"to_act\":0,\"revealed\":null}}\n\nevent: your_turn\ndata: {\"match\":\"ce0f9060f2a44378e7b6b165b18e5be0\",\"seq\":0,\"deadline_ms\":1791344466888,\"now_ms\":1791344465012}\n\nevent: ended\ndata: {\"match\":\"ce0f9060f2a44378e7b6b165b18e5be0\",\"replay\":\"/v1/matches/ce0f9060f2a44378e7b6b165b18e5be0/replay\"}","x-events":[{"event":"lanes","description":"The first event of a lanes stream: which lanes it covers.","data":{"type":"object","properties":{"lanes":{"type":"string","description":"The lanes this stream covers: the requested ones this server instance serves.","pattern":"^[0-9a-f]{1,16}$"}},"required":["lanes"]},"example":{"lanes":"0123456789abcdef"}},{"event":"observation","description":"Your seat's view after every change; its id is the seq. The first event of a stream is the current view.","data":{"type":"object","properties":{"match":{"type":"string","description":"The match the event is about (lanes streams).","pattern":"^[0-9a-f]{32}$"},"seq":{"type":"integer","description":"The match's seq (lanes streams)."},"observation":{"type":"object","properties":{"seat":{"type":"integer","description":"Your seat, from 0.","minimum":0},"my_card":{"type":"string","description":"Your card: jack, queen or king."},"history":{"type":"array","description":"The actions so far, in order (null for actions not yet taken)."},"to_act":{"type":"integer","description":"The seat to act, or null when the hand is over."},"revealed":{"description":"Both cards, once the hand is over; null before."}},"required":["seat","my_card","history","to_act","revealed"],"description":"Your seat's view of that match (lanes streams)."}},"required":["match","seq","observation"]},"example":{"match":"ce0f9060f2a44378e7b6b165b18e5be0","seq":0,"observation":{"seat":0,"my_card":"jack","history":[null,null,null],"to_act":0,"revealed":null}}},{"event":"your_turn","description":"Your seat must act: send an action with this seq before the deadline.","data":{"type":"object","properties":{"match":{"type":"string","description":"The match to act in (lanes streams).","pattern":"^[0-9a-f]{32}$"},"seq":{"type":"integer","description":"The seq to send with your action."},"deadline_ms":{"type":"integer","description":"When your time runs out, in milliseconds since the Unix epoch, on the server's clock. An action received after it is refused (too_late).","format":"int64"},"now_ms":{"type":"integer","description":"The server's clock when the event was sent: deadline_ms minus now_ms is the time you have, whatever your own clock says.","format":"int64"}},"required":["match","seq","deadline_ms","now_ms"]},"example":{"match":"ce0f9060f2a44378e7b6b165b18e5be0","seq":0,"deadline_ms":1791344466888,"now_ms":1791344465012}},{"event":"ended","description":"The match is over: a match's stream closes, a lanes stream goes on with the others. Its replay is at the given path.","data":{"type":"object","properties":{"match":{"type":"string","description":"The match that ended (lanes streams).","pattern":"^[0-9a-f]{32}$"},"replay":{"type":"string","description":"Where the match's replay is (GET)."}},"required":["match","replay"]},"example":{"match":"ce0f9060f2a44378e7b6b165b18e5be0","replay":"/v1/matches/ce0f9060f2a44378e7b6b165b18e5be0/replay"}}]}}},"400":{"description":"`invalid_lanes`: The lanes are not first hex digits of match ids (lowercase, each once).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_lanes"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_lanes":{"summary":"The lanes are not first hex digits of match ids (lowercase, each once).","value":{"error":"invalid_lanes"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"429":{"description":"`too_many_streams`: Too many open event streams for this key or IP; close one first. `rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_many_streams","rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"too_many_streams":{"summary":"Too many open event streams for this key or IP; close one first.","value":{"error":"too_many_streams"}},"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/queues/{game}/{preset}":{"post":{"operationId":"post-v1-queues--game--preset","tags":["Lobby"],"summary":"Join a queue in an asset the preset is offered in (latest game version unless given); the stake is the preset's price in that asset (stake may be left out; given, it must be the price). You are matched with others waiting in the same queue, and the stake is escrowed when the match forms.","description":"Join a queue in an asset the preset is offered in (latest game version unless given); the stake is the preset's price in that asset (stake may be left out; given, it must be the price). You are matched with others waiting in the same queue, and the stake is escrowed when the match forms.\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby. Body up to 1024 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"game","in":"path","required":true,"description":"Game id, as in /v1/games.","schema":{"type":"string"},"example":"rps"},{"name":"preset","in":"path","required":true,"description":"Preset name, as in the game's presets.","schema":{"type":"string"},"example":"single"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stake":{"type":"string","description":"Optional: the preset's price in the asset, as a decimal string of base units. Left out, you play at the price; given, it must equal it.","pattern":"^[0-9]+$"},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"version":{"type":"integer","minimum":1,"description":"The game version; the latest when left out."}},"required":["asset"],"additionalProperties":false},"example":{"asset":"play"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"entry":{"type":"string","description":"Your queue entry's id."},"status":{"type":"string","description":"waiting: you are in the queue; a match forms when enough players are.","enum":["waiting"]}},"required":["entry","status"]},"example":{"entry":"3e8da0376ce0f200532559298c0b064479471844b2e39dc299c3c04cb52e7eec","status":"waiting"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`house_play_money_only`: The house's accounts (the house bot) play money only: no USDC queue, challenge or acceptance involves them. `forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["house_play_money_only","forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"house_play_money_only":{"summary":"The house's accounts (the house bot) play money only: no USDC queue, challenge or acceptance involves them.","value":{"error":"house_play_money_only"}},"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`unknown_game`: No such game or version. `unknown_preset`: No such preset for the game, or it is disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unknown_game","unknown_preset"]}},"required":["error"],"additionalProperties":false},"examples":{"unknown_game":{"summary":"No such game or version.","value":{"error":"unknown_game"}},"unknown_preset":{"summary":"No such preset for the game, or it is disabled.","value":{"error":"unknown_preset"}}}}}},"409":{"description":"`game_disabled`: The game is closed for new matches. `insufficient_funds`: Your available balance does not cover the stake or amount. `limit_reached`: You have too many open queue entries, challenges or matches.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["game_disabled","insufficient_funds","limit_reached"]}},"required":["error"],"additionalProperties":false},"examples":{"game_disabled":{"summary":"The game is closed for new matches.","value":{"error":"game_disabled"}},"insufficient_funds":{"summary":"Your available balance does not cover the stake or amount.","value":{"error":"insufficient_funds"}},"limit_reached":{"summary":"You have too many open queue entries, challenges or matches.","value":{"error":"limit_reached"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"422":{"description":"`invalid_offer`: The game, preset, stake or asset is not valid (stake as a decimal string of base units; asset play or usdc). `invalid_stake`: The stake given is not the preset's price in that asset (leave it out to play at the price). `not_offered`: The preset has no price in that asset, so it cannot be played with it. `unsupported_seats`: The preset does not support this many seats.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_offer","invalid_stake","not_offered","unsupported_seats"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_offer":{"summary":"The game, preset, stake or asset is not valid (stake as a decimal string of base units; asset play or usdc).","value":{"error":"invalid_offer"}},"invalid_stake":{"summary":"The stake given is not the preset's price in that asset (leave it out to play at the price).","value":{"error":"invalid_stake"}},"not_offered":{"summary":"The preset has no price in that asset, so it cannot be played with it.","value":{"error":"not_offered"}},"unsupported_seats":{"summary":"The preset does not support this many seats.","value":{"error":"unsupported_seats"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}},"delete":{"operationId":"delete-v1-queues--game--preset","tags":["Lobby"],"summary":"Leave a queue (the asset you joined with).","description":"Leave a queue (the asset you joined with).\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby. Body up to 1024 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"game","in":"path","required":true,"description":"Game id, as in /v1/games.","schema":{"type":"string"},"example":"rps"},{"name":"preset","in":"path","required":true,"description":"Preset name, as in the game's presets.","schema":{"type":"string"},"example":"single"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stake":{"type":"string","description":"Optional: the stake you joined at (the price).","pattern":"^[0-9]+$"},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"version":{"type":"integer","minimum":1,"description":"The game version; the latest when left out."}},"required":["asset"],"additionalProperties":false},"example":{"asset":"play"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"left: you are out of the queue.","enum":["left"]}},"required":["status"]},"example":{"status":"left"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`invalid_offer`: The game, preset, stake or asset is not valid (stake as a decimal string of base units; asset play or usdc).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_offer"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_offer":{"summary":"The game, preset, stake or asset is not valid (stake as a decimal string of base units; asset play or usdc).","value":{"error":"invalid_offer"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/challenges":{"post":{"operationId":"post-v1-challenges","tags":["Lobby"],"summary":"Challenge a user (opponent: their user id), or anyone (no opponent), to a two-seat match at the preset's price in the asset (stake may be left out; given, it must be the price). It is open for 10 minutes.","description":"Challenge a user (opponent: their user id), or anyone (no opponent), to a two-seat match at the preset's price in the asset (stake may be left out; given, it must be the price). It is open for 10 minutes.\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby. Body up to 1024 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"version":{"type":"integer","minimum":1,"description":"The game version; the latest when left out."},"preset":{"type":"string","description":"The preset's name, as in the game's presets."},"stake":{"type":"string","description":"Optional: the preset's price in the asset, as a decimal string of base units. Left out, the challenge is at the price; given, it must equal it.","pattern":"^[0-9]+$"},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"opponent":{"type":["string","null"],"description":"The user id of who may accept; null or left out: anyone may.","pattern":"^[0-9a-f]{32}$"}},"required":["game","preset","asset"],"additionalProperties":false},"example":{"game":"kuhn","version":1,"preset":"standard","asset":"play","opponent":"325e46fae23fdbca9885ecc43625029e"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"challenge":{"type":"string","description":"The challenge's id, for accepting or declining it.","pattern":"^[0-9a-f]{32}$"},"status":{"type":"string","description":"open: waiting to be accepted until it expires.","enum":["open"]}},"required":["challenge","status"]},"example":{"challenge":"e71c97d58d1bfc2c938746dfa789bae0","status":"open"}}},"links":{"accept":{"operationId":"post-v1-challenges--id-accept","parameters":{"id":"$response.body#/challenge"}},"decline":{"operationId":"post-v1-challenges--id-decline","parameters":{"id":"$response.body#/challenge"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`house_play_money_only`: The house's accounts (the house bot) play money only: no USDC queue, challenge or acceptance involves them. `forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["house_play_money_only","forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"house_play_money_only":{"summary":"The house's accounts (the house bot) play money only: no USDC queue, challenge or acceptance involves them.","value":{"error":"house_play_money_only"}},"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`unknown_game`: No such game or version. `unknown_preset`: No such preset for the game, or it is disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unknown_game","unknown_preset"]}},"required":["error"],"additionalProperties":false},"examples":{"unknown_game":{"summary":"No such game or version.","value":{"error":"unknown_game"}},"unknown_preset":{"summary":"No such preset for the game, or it is disabled.","value":{"error":"unknown_preset"}}}}}},"409":{"description":"`game_disabled`: The game is closed for new matches. `insufficient_funds`: Your available balance does not cover the stake or amount. `limit_reached`: You have too many open queue entries, challenges or matches.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["game_disabled","insufficient_funds","limit_reached"]}},"required":["error"],"additionalProperties":false},"examples":{"game_disabled":{"summary":"The game is closed for new matches.","value":{"error":"game_disabled"}},"insufficient_funds":{"summary":"Your available balance does not cover the stake or amount.","value":{"error":"insufficient_funds"}},"limit_reached":{"summary":"You have too many open queue entries, challenges or matches.","value":{"error":"limit_reached"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`invalid_offer`: The game, preset, stake or asset is not valid (stake as a decimal string of base units; asset play or usdc). `invalid_stake`: The stake given is not the preset's price in that asset (leave it out to play at the price). `not_offered`: The preset has no price in that asset, so it cannot be played with it. `unsupported_seats`: The preset does not support this many seats.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_offer","invalid_stake","not_offered","unsupported_seats"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_offer":{"summary":"The game, preset, stake or asset is not valid (stake as a decimal string of base units; asset play or usdc).","value":{"error":"invalid_offer"}},"invalid_stake":{"summary":"The stake given is not the preset's price in that asset (leave it out to play at the price).","value":{"error":"invalid_stake"}},"not_offered":{"summary":"The preset has no price in that asset, so it cannot be played with it.","value":{"error":"not_offered"}},"unsupported_seats":{"summary":"The preset does not support this many seats.","value":{"error":"unsupported_seats"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/challenges/{id}/accept":{"post":{"operationId":"post-v1-challenges--id-accept","tags":["Lobby"],"summary":"Accept a challenge: both stakes are escrowed and the match starts; returns the match id.","description":"Accept a challenge: both stakes are escrowed and the match starts; returns the match id.\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Challenge id, from POST /v1/challenges or the lobby.","schema":{"type":"string"},"example":"e71c97d58d1bfc2c938746dfa789bae0"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"match":{"type":"string","description":"The match's id: follow it with GET /v1/matches/{id}/events.","pattern":"^[0-9a-f]{32}$"}},"required":["match"]},"example":{"match":"ce0f9060f2a44378e7b6b165b18e5be0"}}},"links":{"follow":{"operationId":"get-v1-matches--id-events","parameters":{"id":"$response.body#/match"}},"view":{"operationId":"get-v1-matches--id","parameters":{"id":"$response.body#/match"}},"act":{"operationId":"post-v1-matches--id-actions","parameters":{"id":"$response.body#/match"}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`not_allowed`: The challenge is addressed to someone else, or it is your own. `house_play_money_only`: The house's accounts (the house bot) play money only: no USDC queue, challenge or acceptance involves them. `forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_allowed","house_play_money_only","forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"not_allowed":{"summary":"The challenge is addressed to someone else, or it is your own.","value":{"error":"not_allowed"}},"house_play_money_only":{"summary":"The house's accounts (the house bot) play money only: no USDC queue, challenge or acceptance involves them.","value":{"error":"house_play_money_only"}},"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"409":{"description":"`challenge_closed`: The challenge was accepted, declined, cancelled or expired. `insufficient_funds`: Your available balance does not cover the stake or amount. `game_disabled`: The game is closed for new matches. `limit_reached`: You have too many open queue entries, challenges or matches.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["challenge_closed","insufficient_funds","game_disabled","limit_reached"]}},"required":["error"],"additionalProperties":false},"examples":{"challenge_closed":{"summary":"The challenge was accepted, declined, cancelled or expired.","value":{"error":"challenge_closed"}},"insufficient_funds":{"summary":"Your available balance does not cover the stake or amount.","value":{"error":"insufficient_funds"}},"game_disabled":{"summary":"The game is closed for new matches.","value":{"error":"game_disabled"}},"limit_reached":{"summary":"You have too many open queue entries, challenges or matches.","value":{"error":"limit_reached"}}}}}},"421":{"description":"`misdirected`: Another server instance owns this match; retry and the load balancer routes you right.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["misdirected"]}},"required":["error"],"additionalProperties":false},"examples":{"misdirected":{"summary":"Another server instance owns this match; retry and the load balancer routes you right.","value":{"error":"misdirected"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/challenges/{id}/decline":{"post":{"operationId":"post-v1-challenges--id-decline","tags":["Lobby"],"summary":"Decline a challenge addressed to you (or cancel your own).","description":"Decline a challenge addressed to you (or cancel your own).\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Challenge id, from POST /v1/challenges or the lobby.","schema":{"type":"string"},"example":"e71c97d58d1bfc2c938746dfa789bae0"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"declined: the challenge is closed.","enum":["declined"]}},"required":["status"]},"example":{"status":"declined"}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`not_allowed`: The challenge is addressed to someone else, or it is your own. `forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_allowed","forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"not_allowed":{"summary":"The challenge is addressed to someone else, or it is your own.","value":{"error":"not_allowed"}},"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"409":{"description":"`challenge_closed`: The challenge was accepted, declined, cancelled or expired.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["challenge_closed"]}},"required":["error"],"additionalProperties":false},"examples":{"challenge_closed":{"summary":"The challenge was accepted, declined, cancelled or expired.","value":{"error":"challenge_closed"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/lobby":{"get":{"operationId":"get-v1-lobby","tags":["Lobby"],"summary":"Your queue entries and the open challenges you made or received.","description":"Your queue entries and the open challenges you made or received.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"queues":{"type":"array","items":{"type":"object","properties":{"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"version":{"type":"integer","description":"The game's version. Rules never change within a version.","minimum":1},"preset":{"type":"string","description":"The preset's name, as in the game's presets."},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"status":{"type":"string","description":"Your entry's state: waiting, or matching while a match forms.","enum":["waiting","matching"]}},"required":["game","version","preset","asset","stake","status"]},"description":"Queues with someone waiting."},"challenges":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The challenge's id.","pattern":"^[0-9a-f]{32}$"},"challenger":{"type":"string","description":"The user id of who made the challenge.","pattern":"^[0-9a-f]{32}$"},"opponent":{"type":["string","null"],"description":"The user id of who may accept; null or left out: anyone may.","pattern":"^[0-9a-f]{32}$"},"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"preset":{"type":"string","description":"The preset's name, as in the game's presets."},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"stake":{"type":"string","description":"The stake per seat, a decimal string of base units.","pattern":"^[0-9]+$"},"expires_at_ms":{"type":"integer","description":"When it expires, in milliseconds since the Unix epoch.","format":"int64"}},"required":["id","challenger","opponent","game","preset","asset","stake","expires_at_ms"]},"description":"Open challenges you made or that are addressed to you."}},"required":["queues","challenges"]},"example":{"queues":[{"game":"rps","version":1,"preset":"single","asset":"play","stake":"1","status":"waiting"}],"challenges":[{"id":"e71c97d58d1bfc2c938746dfa789bae0","challenger":"861b4c154d136e501967e613deded8b4","opponent":"325e46fae23fdbca9885ecc43625029e","game":"kuhn","preset":"standard","asset":"play","stake":"2","expires_at_ms":1791345061670}]}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/withdrawals":{"post":{"operationId":"post-v1-withdrawals","tags":["Account and money"],"summary":"Withdraw USDC (base units, 6 decimals), always to your own wallet. Limits apply; above the threshold an admin approves it first. A repeat with the same idempotency_key returns the same withdrawal.","description":"Withdraw USDC (base units, 6 decimals), always to your own wallet. Limits apply; above the threshold an admin approves it first. A repeat with the same idempotency_key returns the same withdrawal.\n\nAccess: an API key with scope withdraw, or a wallet session. Rate class: money_out. Body up to 512 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"idempotency_key":{"type":"string","description":"Your id for this request (1 to 64 characters), unique per withdrawal. Sending it again returns the same withdrawal, never a second one."},"amount":{"type":"string","description":"USDC to withdraw, a decimal string of base units (1 USDC = 1,000,000).","pattern":"^[0-9]+$"}},"required":["idempotency_key","amount"],"additionalProperties":false},"example":{"idempotency_key":"payout-2026-10-07","amount":"25000000"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The withdrawal's id: follow it with GET /v1/withdrawals/{id}.","pattern":"^[0-9a-f]{32}$"},"status":{"type":"string","description":"requested: accepted, and waiting for approval or payout.","enum":["requested"]},"needs_approval":{"type":"boolean","description":"Whether an admin must approve it first (above the approval threshold)."}},"required":["id","status","needs_approval"]},"example":{"id":"4c8e1a2b9d3f40e6a7b5c1d2e3f40516","status":"requested","needs_approval":false}}},"links":{"track":{"operationId":"get-v1-withdrawals--id","parameters":{"id":"$response.body#/id"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"409":{"description":"`insufficient_funds`: Your available balance does not cover the stake or amount. `daily_limit`: The withdrawal would exceed your daily limit. `velocity_limit`: Too many withdrawals in a short time; try later. `idempotency_conflict`: This idempotency_key was used for a different request. `no_wallet`: No wallet is linked to the account to withdraw to. `account_on_hold`: Withdrawals are on hold for this account; contact support.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["insufficient_funds","daily_limit","velocity_limit","idempotency_conflict","no_wallet","account_on_hold"]}},"required":["error"],"additionalProperties":false},"examples":{"insufficient_funds":{"summary":"Your available balance does not cover the stake or amount.","value":{"error":"insufficient_funds"}},"daily_limit":{"summary":"The withdrawal would exceed your daily limit.","value":{"error":"daily_limit"}},"velocity_limit":{"summary":"Too many withdrawals in a short time; try later.","value":{"error":"velocity_limit"}},"idempotency_conflict":{"summary":"This idempotency_key was used for a different request.","value":{"error":"idempotency_conflict"}},"no_wallet":{"summary":"No wallet is linked to the account to withdraw to.","value":{"error":"no_wallet"}},"account_on_hold":{"summary":"Withdrawals are on hold for this account; contact support.","value":{"error":"account_on_hold"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`invalid_amount`: The amount is not a positive decimal string of base units. `amount_limit`: The amount is above the per-withdrawal limit.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_amount","amount_limit"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_amount":{"summary":"The amount is not a positive decimal string of base units.","value":{"error":"invalid_amount"}},"amount_limit":{"summary":"The amount is above the per-withdrawal limit.","value":{"error":"amount_limit"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/withdrawals/{id}":{"get":{"operationId":"get-v1-withdrawals--id","tags":["Account and money"],"summary":"A withdrawal's status: requested, approved, broadcast, confirmed, failed or released.","description":"A withdrawal's status: requested, approved, broadcast, confirmed, failed or released.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Withdrawal id, from POST /v1/withdrawals.","schema":{"type":"string"},"example":"4c8e1a2b9d3f40e6a7b5c1d2e3f40516"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The withdrawal's id.","pattern":"^[0-9a-f]{32}$"},"asset":{"type":"string","description":"The currency: play (play money, whole units) or usdc (USDC in base units, 6 decimals).","enum":["play","usdc"]},"amount":{"type":"string","description":"The amount, a decimal string of base units.","pattern":"^[0-9]+$"},"status":{"type":"string","description":"requested (waiting for an admin, above the threshold), approved, broadcast (sent, waiting for confirmations), confirmed (final: paid), failed (the payout failed; the amount is back in your balance) or released (rejected by an admin; the amount is back).","enum":["requested","approved","broadcast","confirmed","failed","released"]},"needs_approval":{"type":"boolean","description":"Whether an admin must approve it first (above the approval threshold)."},"reference":{"type":["string","null"],"description":"The payout's transaction hash once sent; null before."},"reason":{"description":"Why it was rejected or failed; null otherwise.","type":["string","null"]},"created_at_ms":{"type":"integer","description":"When it was created, in milliseconds since the Unix epoch.","format":"int64"},"updated_at_ms":{"type":"integer","description":"When it last changed, in milliseconds since the Unix epoch.","format":"int64"}},"required":["id","asset","amount","status","needs_approval","reference","reason","created_at_ms","updated_at_ms"]},"example":{"id":"4c8e1a2b9d3f40e6a7b5c1d2e3f40516","asset":"usdc","amount":"25000000","status":"confirmed","needs_approval":false,"reference":"0x6f1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c","reason":null,"created_at_ms":1791344461700,"updated_at_ms":1791344521700}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account/transactions":{"get":{"operationId":"get-v1-account-transactions","tags":["Account and money"],"summary":"Your ledger movements, newest first, 50 per page.","description":"Your ledger movements, newest first, 50 per page.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"before","in":"query","required":false,"description":"The next value of the previous page.","schema":{"type":"string"},"example":""}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"movements":{"type":"array","items":{"type":"object","properties":{"at_ms":{"type":"integer","description":"When it happened, in milliseconds since the Unix epoch.","format":"int64"},"asset":{"type":"string","description":"The currency.","enum":["play","usdc"]},"account":{"type":"string","description":"Which of your balances moved.","enum":["available","pending","withdrawing"]},"amount":{"type":"string","description":"The change, a signed decimal string of base units.","pattern":"^-?[0-9]+$"},"kind":{"type":"string","description":"What caused it: a deposit seen, final or reversed; a withdrawal reserved, paid or released; a stake held (escrow), a match paid out (settle) or refunded; a fee; play money granted; an admin adjustment; an integrity hold and its outcome; or a referral reward.","enum":["deposit_seen","deposit_final","deposit_reversed","withdrawal_reserve","withdrawal_paid","withdrawal_release","escrow","settle","refund","fee","adjustment","play_grant","freeze","unfreeze","freeze_return","forfeit","referral_reward"]},"cause":{"type":"string","description":"What it belongs to: a match id, a withdrawal id or a deposit's transaction; empty when nothing."}},"required":["at_ms","asset","account","amount","kind","cause"]},"description":"Your balance changes, newest first: one row per account and currency a transaction touched."},"next":{"description":"The cursor for the next (older) page: pass it as ?before=<next>. Null on the last page.","type":["string","null"]}},"required":["movements","next"]},"example":{"movements":[{"at_ms":1791344467888,"asset":"play","account":"available","amount":"1","kind":"settle","cause":"ce0f9060f2a44378e7b6b165b18e5be0"},{"at_ms":1791344461742,"asset":"play","account":"available","amount":"-2","kind":"escrow","cause":"ce0f9060f2a44378e7b6b165b18e5be0"}],"next":null}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/auth/challenge":{"post":{"operationId":"post-v1-auth-challenge","tags":["Sign-in"],"summary":"The message for a wallet to sign (EIP-4361), with a single-use nonce that expires soon (the message says when).","description":"The message for a wallet to sign (EIP-4361), with a single-use nonce that expires soon (the message says when).\n\nAccess: public, no credential. Rate class: auth. Body up to 256 bytes.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string","description":"Your wallet address: 0x and 40 hex digits, any case.","pattern":"^0x[0-9a-fA-F]{40}$"}},"required":["address"],"additionalProperties":false},"example":{"address":"0xF0695a7F0FeCbDcb200163b316C2C3e087321A4a"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"The sign-in message (EIP-4361) for your wallet to sign with personal_sign. It names this site, your address and a single-use nonce, and expires soon (its Expiration Time)."}},"required":["message"]},"example":{"message":"degenprotocol.example wants you to sign in with your Ethereum account:\n0xF0695a7F0FeCbDcb200163b316C2C3e087321A4a\n\nSign in to Degen Protocol.\n\nURI: https://degenprotocol.example\nVersion: 1\nChain ID: 8453\nNonce: 0b6411964971e333d88d1ad72512431b\nIssued At: 2026-10-07T03:41:01Z\nExpiration Time: 2026-10-07T03:46:01Z"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`invalid_address`: Not an Ethereum address.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_address"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_address":{"summary":"Not an Ethereum address.","value":{"error":"invalid_address"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}},"503":{"description":"`sign_in_unavailable`: Sign-in is not ready yet on this server; retry shortly.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["sign_in_unavailable"]}},"required":["error"],"additionalProperties":false},"examples":{"sign_in_unavailable":{"summary":"Sign-in is not ready yet on this server; retry shortly.","value":{"error":"sign_in_unavailable"}}}}}}}}},"/v1/auth/sign-in":{"post":{"operationId":"post-v1-auth-sign-in","tags":["Sign-in"],"summary":"Sign in with the signed message (personal_sign): a session token for Authorization: Bearer (expires_at_ms says until when), and a browser cookie with its CSRF token. The first sign-in makes the account; pass a referral code to name the account that referred you.","description":"Sign in with the signed message (personal_sign): a session token for Authorization: Bearer (expires_at_ms says until when), and a browser cookie with its CSRF token. The first sign-in makes the account; pass a referral code to name the account that referred you.\n\nAccess: public, no credential. Rate class: auth. Body up to 4096 bytes.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"The message from POST /v1/auth/challenge, exactly as it was returned."},"signature":{"type":"string","description":"Your wallet's personal_sign signature of the message: 0x and 130 hex digits.","pattern":"^0x[0-9a-fA-F]{130}$"},"referral":{"type":"string","description":"Optional: the referral code of the account that referred you. Used only when the sign-in makes a new account (or one still within its claim window); a bad code never fails the sign-in.","pattern":"^[A-Za-z0-9]{8}$"}},"required":["message","signature"],"additionalProperties":false},"example":{"message":"<the message from /v1/auth/challenge>","signature":"0x<65-byte signature, hex>","referral":"K7M2Q9XA"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The session token: send it as Authorization: Bearer <token>. It works until expires_at_ms; creating or revoking API keys needs a recent signature (sign in again when GET /v1/auth/session says it is not fresh)."},"expires_at_ms":{"type":"integer","description":"When the session ends, in milliseconds since the Unix epoch.","format":"int64"},"csrf":{"type":"string","description":"The CSRF token for browser requests with the session cookie: send it as the x-degen-csrf header on requests other than GET."},"address":{"type":"string","description":"The address that signed, checksummed."},"user_id":{"type":"string","description":"Your account id: 32 hex characters, stable for the account.","pattern":"^[0-9a-f]{32}$"},"role":{"description":"Always null on the public API (admin roles live on the admin console).","type":["string","null"]}},"required":["token","expires_at_ms","csrf","address","user_id","role"]},"example":{"token":"<session token>","expires_at_ms":1791387661434,"csrf":"<csrf token>","address":"0xF0695a7F0FeCbDcb200163b316C2C3e087321A4a","user_id":"861b4c154d136e501967e613deded8b4","role":null}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`sign_in_failed`: The signed message or signature is not valid: wrong domain, expired, a nonce already used, or signed by another address.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["sign_in_failed"]}},"required":["error"],"additionalProperties":false},"examples":{"sign_in_failed":{"summary":"The signed message or signature is not valid: wrong domain, expired, a nonce already used, or signed by another address.","value":{"error":"sign_in_failed"}}}}}},"403":{"description":"`account_suspended`: An admin suspended this account for now; its sessions and keys do not work until the suspension ends. `account_blocked`: An admin blocked this account; contact support.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["account_suspended","account_blocked"]}},"required":["error"],"additionalProperties":false},"examples":{"account_suspended":{"summary":"An admin suspended this account for now; its sessions and keys do not work until the suspension ends.","value":{"error":"account_suspended"}},"account_blocked":{"summary":"An admin blocked this account; contact support.","value":{"error":"account_blocked"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}},"503":{"description":"`sign_in_unavailable`: Sign-in is not ready yet on this server; retry shortly.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["sign_in_unavailable"]}},"required":["error"],"additionalProperties":false},"examples":{"sign_in_unavailable":{"summary":"Sign-in is not ready yet on this server; retry shortly.","value":{"error":"sign_in_unavailable"}}}}}}}}},"/v1/auth/sign-out":{"post":{"operationId":"post-v1-auth-sign-out","tags":["Sign-in"],"summary":"End the session.","description":"End the session.\n\nAccess: a wallet session only (API keys are refused). Rate class: auth.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"signed_out":{"type":"boolean","description":"True: the session is ended and its token no longer works."}},"required":["signed_out"]},"example":{"signed_out":true}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/auth/session":{"get":{"operationId":"get-v1-auth-session","tags":["Sign-in"],"summary":"Who is signed in, and whether the signature is fresh enough for key management.","description":"Who is signed in, and whether the signature is fresh enough for key management.\n\nAccess: a wallet session only (API keys are refused). Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","description":"Your account id: 32 hex characters, stable for the account.","pattern":"^[0-9a-f]{32}$"},"address":{"type":"string","description":"The signed-in wallet address, lowercase."},"signed_at_ms":{"type":"integer","description":"When the wallet signed in for this session, in milliseconds since the Unix epoch.","format":"int64"},"fresh":{"type":"boolean","description":"Whether the signature is recent enough to create or revoke API keys; when it is not, sign in again."}},"required":["user_id","address","signed_at_ms","fresh"]},"example":{"user_id":"861b4c154d136e501967e613deded8b4","address":"0xf0695a7f0fecbdcb200163b316c2c3e087321a4a","signed_at_ms":1791344461434,"fresh":true}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account/keys":{"get":{"operationId":"get-v1-account-keys","tags":["Sign-in"],"summary":"Your API keys: label, scopes, created, expiry, revoked. Wallet session only.","description":"Your API keys: label, scopes, created, expiry, revoked. Wallet session only.\n\nAccess: a wallet session only (API keys are refused). Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"prefix":{"type":"string","description":"The key's public prefix: the 8 characters after degen_. Identifies the key in lists and for revoking.","pattern":"^[0-9a-f]{8}$"},"label":{"type":"string","description":"The key's label."},"scopes":{"type":"array","items":{"type":"string","enum":["read","play","withdraw"]},"description":"What the key may do: read, play and withdraw."},"created_at_ms":{"type":"integer","description":"When the key was created, in milliseconds since the Unix epoch.","format":"int64"},"expires_at_ms":{"description":"When the key stops working; null if it never expires.","format":"int64","type":["integer","null"]},"revoked_at_ms":{"description":"When the key was revoked; null while it works.","format":"int64","type":["integer","null"]}},"required":["prefix","label","scopes","created_at_ms","expires_at_ms","revoked_at_ms"]},"description":"Your API keys, newest first."}},"required":["keys"]},"example":{"keys":[{"prefix":"e36594dd","label":"my bot","scopes":["read","play"],"created_at_ms":1791344461496,"expires_at_ms":null,"revoked_at_ms":null}]}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/keys":{"post":{"operationId":"post-v1-keys","tags":["Sign-in"],"summary":"Create an API key (label, scopes read/play/withdraw, optional expiry in days). The key is shown once. Needs a fresh wallet signature.","description":"Create an API key (label, scopes read/play/withdraw, optional expiry in days). The key is shown once. Needs a fresh wallet signature.\n\nAccess: a wallet session only (API keys are refused). The wallet signature must be recent (sign in again if it is not). Rate class: keys. Body up to 512 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"A name for the key so you can tell keys apart: 1 to 64 letters, digits, spaces, dots, dashes or underscores."},"scopes":{"type":"array","items":{"type":"string"},"description":"What the key may do: read (games, matches, your account), play (lobby and actions) and withdraw (opt-in: USDC to your signed-in wallet). At least one."},"expires_in_days":{"type":"integer","minimum":1,"description":"Days until the key stops working, 1 to 365. Left out, it never expires.","maximum":365}},"required":["label","scopes"],"additionalProperties":false},"example":{"label":"my bot","scopes":["read","play"],"expires_in_days":90}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","description":"The API key: degen_<prefix>_<secret>. Shown once and not stored; keep it secret."},"prefix":{"type":"string","description":"The key's public prefix: the 8 characters after degen_. Identifies the key in lists and for revoking.","pattern":"^[0-9a-f]{8}$"},"scopes":{"type":"array","items":{"type":"string"},"description":"What the key may do: read (games, matches, your account), play (lobby and actions) and withdraw (opt-in: USDC to your signed-in wallet). At least one."},"expires_at_ms":{"type":["integer","null"],"description":"When the key stops working; null if it never expires.","format":"int64"}},"required":["key","prefix","scopes","expires_at_ms"]},"example":{"key":"degen_e36594dd_<secret>","prefix":"e36594dd","scopes":["read","play"],"expires_at_ms":1799120461496}}},"links":{"revoke":{"operationId":"delete-v1-keys--prefix","parameters":{"prefix":"$response.body#/prefix"}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`invalid_label`: The label is empty, too long or has characters other than letters, digits, spaces, dots, dashes and underscores. `invalid_scopes`: Scopes must be a non-empty list of read, play and withdraw. `invalid_expiry`: expires_in_days must be between 1 and 365.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_label","invalid_scopes","invalid_expiry"]}},"required":["error"],"additionalProperties":false},"examples":{"invalid_label":{"summary":"The label is empty, too long or has characters other than letters, digits, spaces, dots, dashes and underscores.","value":{"error":"invalid_label"}},"invalid_scopes":{"summary":"Scopes must be a non-empty list of read, play and withdraw.","value":{"error":"invalid_scopes"}},"invalid_expiry":{"summary":"expires_in_days must be between 1 and 365.","value":{"error":"invalid_expiry"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/keys/{prefix}":{"delete":{"operationId":"delete-v1-keys--prefix","tags":["Sign-in"],"summary":"Revoke one of your API keys; its open streams close. Needs a fresh wallet signature.","description":"Revoke one of your API keys; its open streams close. Needs a fresh wallet signature.\n\nAccess: a wallet session only (API keys are refused). The wallet signature must be recent (sign in again if it is not). Rate class: keys.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"prefix","in":"path","required":true,"description":"The key's prefix (the 8 characters after degen_).","schema":{"type":"string"},"example":"e36594dd"},{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"revoked":{"type":"string","description":"The prefix of the key revoked."}},"required":["revoked"]},"example":{"revoked":"e36594dd"}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`not_found`: No such thing, or it is not yours.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_found"]}},"required":["error"],"additionalProperties":false},"examples":{"not_found":{"summary":"No such thing, or it is not yours.","value":{"error":"not_found"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account/referrals":{"get":{"operationId":"get-v1-account-referrals","tags":["Referrals"],"summary":"Your referral code and link, who referred you, and the accounts you referred with what each earned you. Share the code or link; for as long as each referred account plays (unless admins set a time limit), you earn a share of what the house earns from its USDC matches, paid in USDC; play money earns nothing.","description":"Your referral code and link, who referred you, and the accounts you referred with what each earned you. Share the code or link; for as long as each referred account plays (unless admins set a time limit), you earn a share of what the house earns from its USDC matches, paid in USDC; play money earns nothing.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Your referral code: 8 letters and digits, never changes. Others pass it at sign-in or claim it.","pattern":"^[A-HJ-KM-NP-Z2-9]{8}$"},"link":{"type":"string","description":"Your referral link: a visitor who signs in after opening it is referred by you."},"referred_by":{"description":"The account that referred you, or null.","pattern":"^[0-9a-f]{32}$","type":["string","null"]},"referred_by_name":{"description":"That account's display name, or null.","type":["string","null"]},"claim_until_ms":{"type":["integer","null"],"description":"Until when you can still name a referrer (POST /v1/account/referrer), in milliseconds since the Unix epoch; null when you cannot (you have one, or the window closed).","format":"int64"},"rewards":{"type":"object","properties":{"on":{"type":"boolean","description":"Whether rewards are being paid."},"share_percent":{"type":"integer","description":"Your share, in percent, of the house's fees and rake from the USDC matches of the accounts you referred. Admins may set it per account.","minimum":0,"maximum":50},"period_ms":{"type":"integer","description":"How long after an account is referred its referrer earns from it, in milliseconds; 0: for as long as it plays."}},"required":["on","share_percent","period_ms"],"description":"What referring earns now."},"referred":{"type":"integer","description":"How many accounts you referred."},"active":{"type":"integer","description":"How many of them still earn you rewards."},"earned":{"type":"array","items":{"type":"object","properties":{"asset":{"type":"string","description":"The currency.","enum":["play","usdc"]},"amount":{"type":"string","description":"Earned, in base units.","pattern":"^[0-9]+$"}},"required":["asset","amount"]},"description":"Rewards earned, per currency."},"referrals":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","description":"The referred account's id.","pattern":"^[0-9a-f]{32}$"},"display_name":{"type":["string","null"],"description":"Its display name, or null."},"at_ms":{"type":"integer","description":"When it was referred, in milliseconds since the Unix epoch.","format":"int64"},"until_ms":{"description":"When its rewards end, in milliseconds since the Unix epoch; null: they do not.","format":"int64","type":["integer","null"]},"active":{"type":"boolean","description":"Whether it still earns you rewards."},"ended":{"type":"boolean","description":"Whether the referral was ended early by the platform (abuse)."},"earned":{"type":"array","items":{"type":"object","properties":{"asset":{"type":"string","description":"The currency.","enum":["play","usdc"]},"amount":{"type":"string","description":"Earned, in base units.","pattern":"^[0-9]+$"}},"required":["asset","amount"]},"description":"Rewards earned, per currency."}},"required":["user_id","display_name","at_ms","until_ms","active","ended","earned"]},"description":"The accounts you referred, newest first (at most 100)."}},"required":["code","link","referred_by","referred_by_name","claim_until_ms","rewards","referred","active","earned","referrals"]},"example":{"code":"K7M2Q9XA","link":"https://degenprotocol.example/r/K7M2Q9XA","referred_by":null,"referred_by_name":null,"claim_until_ms":1791949261434,"rewards":{"on":true,"share_percent":20,"period_ms":0},"referred":1,"active":1,"earned":[{"asset":"usdc","amount":"125000"},{"asset":"play","amount":"4800"}],"referrals":[{"user_id":"325e46fae23fdbca9885ecc43625029e","display_name":"Monte","at_ms":1791344461434,"until_ms":null,"active":true,"ended":false,"earned":[{"asset":"usdc","amount":"125000"},{"asset":"play","amount":"4800"}]}]}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/account/referrer":{"post":{"operationId":"post-v1-account-referrer","tags":["Referrals"],"summary":"Name the account that referred you, by its code: once, soon after your account was made (claim_until_ms). A code passed at sign-in or a referral link does the same.","description":"Name the account that referred you, by its code: once, soon after your account was made (claim_until_ms). A code passed at sign-in or a referral link does the same.\n\nAccess: an API key with scope play, or a wallet session. Rate class: play_lobby. Body up to 256 bytes.","security":[{"bearer":[]},{"session_cookie":[]}],"parameters":[{"name":"x-degen-csrf","in":"header","required":false,"description":"Only with the browser session cookie: the degen_csrf cookie's value (or the csrf from sign-in). Not needed with Authorization: Bearer.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"The referral code of the account that referred you, any case.","pattern":"^[A-Za-z0-9]{8}$"}},"required":["code"],"additionalProperties":false},"example":{"code":"K7M2Q9XA"}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"referred_by":{"type":"string","description":"The account that referred you.","pattern":"^[0-9a-f]{32}$"},"at_ms":{"type":"integer","description":"When the referral was made, in milliseconds since the Unix epoch.","format":"int64"},"until_ms":{"description":"Until when the account that referred you earns from your matches, in milliseconds since the Unix epoch; null: for as long as you play.","format":"int64","type":["integer","null"]}},"required":["referred_by","at_ms","until_ms"]},"example":{"referred_by":"861b4c154d136e501967e613deded8b4","at_ms":1791344461434,"until_ms":null}}}},"400":{"description":"`bad_request`: The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["bad_request"]}},"required":["error"],"additionalProperties":false},"examples":{"bad_request":{"summary":"The body or query is not what the route takes: invalid JSON, a missing or unknown field, or a wrong type.","value":{"error":"bad_request"}}}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"404":{"description":"`unknown_code`: No account has this referral code (codes are 8 letters and digits, any case).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unknown_code"]}},"required":["error"],"additionalProperties":false},"examples":{"unknown_code":{"summary":"No account has this referral code (codes are 8 letters and digits, any case).","value":{"error":"unknown_code"}}}}}},"409":{"description":"`already_referred`: Your account already has a referrer; it never changes. `claim_window_closed`: A referrer can be named only soon after an account is made; GET /v1/account/referrals says until when (claim_until_ms).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["already_referred","claim_window_closed"]}},"required":["error"],"additionalProperties":false},"examples":{"already_referred":{"summary":"Your account already has a referrer; it never changes.","value":{"error":"already_referred"}},"claim_window_closed":{"summary":"A referrer can be named only soon after an account is made; GET /v1/account/referrals says until when (claim_until_ms).","value":{"error":"claim_window_closed"}}}}}},"413":{"description":"`too_large`: The body is larger than the route accepts.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["too_large"]}},"required":["error"],"additionalProperties":false},"examples":{"too_large":{"summary":"The body is larger than the route accepts.","value":{"error":"too_large"}}}}}},"422":{"description":"`self_referral`: That is your own referral code. `mutual_referral`: That account was referred by you; two accounts cannot refer each other. `house_account`: The house's accounts neither refer nor are referred.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["self_referral","mutual_referral","house_account"]}},"required":["error"],"additionalProperties":false},"examples":{"self_referral":{"summary":"That is your own referral code.","value":{"error":"self_referral"}},"mutual_referral":{"summary":"That account was referred by you; two accounts cannot refer each other.","value":{"error":"mutual_referral"}},"house_account":{"summary":"The house's accounts neither refer nor are referred.","value":{"error":"house_account"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}},"/v1/house/plan":{"get":{"operationId":"get-v1-house-plan","tags":["Platform"],"summary":"For the platform's own house bot: what admins set it to play (on or off, whether it accepts challenges, the presets it keeps a seat waiting in, how many matches at once). Every other account is refused.","description":"For the platform's own house bot: what admins set it to play (on or off, whether it accepts challenges, the presets it keeps a seat waiting in, how many matches at once). Every other account is refused.\n\nAccess: an API key with scope read, or a wallet session. Rate class: read.","security":[{"bearer":[]},{"session_cookie":[]}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the house bot plays at all."},"accept_challenges":{"type":"boolean","description":"Whether it accepts play-money challenges addressed to it."},"queues":{"type":"array","items":{"type":"object","properties":{"game":{"type":"string","description":"The game's id, as in GET /v1/games."},"preset":{"type":"string","description":"The preset's name, as in the game's presets."}},"required":["game","preset"]},"description":"The presets it keeps a seat waiting in."},"max_matches":{"type":"integer","description":"The most matches it plays at once."}},"required":["enabled","accept_challenges","queues","max_matches"]},"example":{"enabled":true,"accept_challenges":true,"queues":[{"game":"kuhn","preset":"standard"}],"max_matches":8}}}},"401":{"description":"`unauthenticated`: No valid credential: none was sent, or the token or key is unknown, expired or revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["unauthenticated"]}},"required":["error"],"additionalProperties":false},"examples":{"unauthenticated":{"summary":"No valid credential: none was sent, or the token or key is unknown, expired or revoked.","value":{"error":"unauthenticated"}}}}}},"403":{"description":"`not_house`: Only the platform's house bot reads its plan. `forbidden`: The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["not_house","forbidden"]}},"required":["error"],"additionalProperties":false},"examples":{"not_house":{"summary":"Only the platform's house bot reads its plan.","value":{"error":"not_house"}},"forbidden":{"summary":"The credential may not do this: an API key without the scope, a key where a wallet session is needed, a wallet signature that is not recent enough, or a browser request without its CSRF header.","value":{"error":"forbidden"}}}}}},"429":{"description":"`rate_limited`: Too many requests; wait as Retry-After says.","headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["rate_limited"]}},"required":["error"],"additionalProperties":false},"examples":{"rate_limited":{"summary":"Too many requests; wait as Retry-After says.","value":{"error":"rate_limited"}}}}}}}}}}}