{"openapi":"3.0.3","info":{"title":"World Street API","description":"The complete public API of the World Street platform, served by the API Gateway — the sole entry point. Endpoints are grouped by owning service (rwa, …) at their public /v1/<service>/... paths and are directly executable here. Every response uses the standard `{ success, data | error }` envelope.\n\n**Currently unreachable services (docs omitted):** ai, payment","version":"0.1.0"},"paths":{"/health":{"get":{"summary":"Gateway health","tags":["meta"],"responses":{"200":{"description":"Gateway is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/{service}/{path}":{"get":{"summary":"Proxy to a registered service (all methods, not just GET)","description":"Requests to /v1/<service>/* are forwarded to the owning microservice with the prefix stripped. Registered services appear in the docs dropdown. Unknown prefixes return 404; an unreachable service returns 502. The gateway forwards approved protocol headers such as Authorization and Idempotency-Key; each owning service verifies bearer tokens and resolves authorization context from its own database. Client-supplied identity or role headers are never forwarded.","tags":["routing"],"parameters":[{"name":"service","in":"path","required":true,"schema":{"type":"string"},"example":"rwa"},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"404":{"description":"Unknown service prefix (NOT_FOUND envelope)"},"429":{"description":"Rate limit exceeded (TOO_MANY_REQUESTS envelope)"},"502":{"description":"Downstream service unreachable (SERVICE_UNAVAILABLE envelope)"}}}},"/v1/rwa/health":{"get":{"summary":"Service health","tags":["rwa"],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_HealthResponse"}}}}}}},"/v1/rwa/categories":{"get":{"summary":"RWA categories with asset counts","tags":["rwa"],"responses":{"200":{"description":"Category list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_CategoryListResponse"}}}}}}},"/v1/rwa/assets":{"get":{"summary":"Curated RWA registry (cached ~60s; filters applied server-side by us)","tags":["rwa"],"parameters":[{"name":"category","in":"query","schema":{"type":"string"},"example":"treasury"},{"name":"chain","in":"query","schema":{"type":"string","enum":["solana","ethereum","base","arbitrum","bsc","polygon"]}},{"name":"freelyTradable","in":"query","schema":{"type":"string","enum":["true","false"]},"description":"Access reality only (open DEX + no transfer restrictions) — not a liquidity opinion."},{"name":"includeDeprecated","in":"query","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Asset list. priceUsd is best-effort and may be null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_AssetListResponse"}}}}}}},"/v1/rwa/assets/{id}":{"get":{"summary":"One RWA asset","tags":["rwa"],"parameters":[{"$ref":"#/components/parameters/rwa_AssetId"}],"responses":{"200":{"description":"The asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_AssetResponse"}}}},"404":{"$ref":"#/components/responses/rwa_NotFound"}}}},"/v1/rwa/assets/{id}/yield-history":{"get":{"summary":"Daily APY + TVL series for yield-bearing assets","tags":["rwa"],"parameters":[{"$ref":"#/components/parameters/rwa_AssetId"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000}}],"responses":{"200":{"description":"Daily points, oldest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_YieldHistoryResponse"}}}},"400":{"description":"Asset is not yield-bearing (code ASSET_NOT_TRADABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_ErrorResponse"}}}},"404":{"$ref":"#/components/responses/rwa_NotFound"}}}},"/v1/rwa/quote":{"post":{"summary":"Quote buying/selling a tradable RWA (never cached; quotes expire)","tags":["rwa"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_QuoteRequest"}}}},"responses":{"200":{"description":"Meta-aggregated quote: best first, alternatives, failures","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_QuoteResponse"}}}},"400":{"$ref":"#/components/responses/rwa_BadRequest"},"404":{"description":"NO_ROUTE — no provider can route this pair"},"422":{"description":"INSUFFICIENT_LIQUIDITY — route exists but cannot fill the size"},"502":{"description":"Upstream RWA provider unavailable (retryable)"}}}},"/v1/rwa/build":{"post":{"summary":"Build signable steps[] for the user wallet (non-custodial)","description":"Returns ordered steps for the CLIENT-SIDE wallet (Privy/Dynamic) to sign and send. The backend never signs or submits. Permissioned assets return 400 ASSET_NOT_TRADABLE with accessMode/kycRequired/issuerUrl details. Actions expire (expiresAt) — rebuild rather than reuse.","tags":["rwa"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_BuildRequest"}}}},"responses":{"200":{"description":"The built action with steps[]","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_ActionResponse"}}}},"400":{"$ref":"#/components/responses/rwa_BadRequest"},"410":{"description":"QUOTE_EXPIRED — request a new build"},"422":{"description":"SIMULATION_FAILED — the transaction reverts for this taker"},"502":{"description":"Upstream RWA provider unavailable (retryable)"}}}},"/v1/trade/health":{"get":{"tags":["trade"],"responses":{"200":{"description":"Healthy"}}}},"/v1/trade/tokens":{"get":{"tags":["trade"],"responses":{"200":{"description":"Automatically refreshed, persisted Base and Solana token catalog"}}}},"/v1/trade/tokens/trending":{"get":{"tags":["trade"],"responses":{"200":{"description":"Live Base and Solana token discovery feed"}}}},"/v1/trade/tokens/search":{"get":{"tags":["trade"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2}}],"responses":{"200":{"description":"Live Base and Solana token matches"}}}},"/v1/trade/tokens/{address}":{"get":{"tags":["trade"],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"200":{"description":"Token details"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"404":{"$ref":"#/components/responses/trade_TokenNotFound"}}}},"/v1/trade/tokens/{address}/market":{"get":{"tags":["trade"],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"200":{"description":"Best-liquidity Base market data"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"404":{"$ref":"#/components/responses/trade_TokenNotFound"}}}},"/v1/trade/tokens/{address}/risk":{"get":{"tags":["trade"],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"200":{"description":"Risk assessment; never a safety guarantee"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"404":{"$ref":"#/components/responses/trade_TokenNotFound"}}}},"/v1/trade/tokens/{address}/tradability":{"get":{"tags":["trade"],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"200":{"description":"Current server-side buy/sell policy"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"404":{"$ref":"#/components/responses/trade_TokenNotFound"}}}},"/v1/trade/wallets/challenges":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"requestBody":{"$ref":"#/components/requestBodies/trade_WalletChallenge"},"responses":{"201":{"description":"Message to sign"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"}}}},"/v1/trade/wallets/verify":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"requestBody":{"$ref":"#/components/requestBodies/trade_WalletVerification"},"responses":{"201":{"description":"Wallet linked to authenticated identity"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"}}}},"/v1/trade/swaps/preview":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"requestBody":{"$ref":"#/components/requestBodies/trade_Swap"},"responses":{"201":{"description":"Indicative preview without calldata"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"},"422":{"$ref":"#/components/responses/trade_TradeRejected"}}}},"/v1/trade/swaps/quote":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/trade_Swap"},"responses":{"201":{"description":"Ordered generic EVM calls"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"},"409":{"description":"Idempotency conflict"},"422":{"$ref":"#/components/responses/trade_TradeRejected"}}}},"/v1/trade/swaps/{swapId}/submissions":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_SwapId"},{"$ref":"#/components/parameters/trade_IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/trade_Submission"},"responses":{"201":{"description":"Execution identifier registered for verification"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"},"404":{"$ref":"#/components/responses/trade_SwapNotFound"},"409":{"description":"Submission or idempotency conflict"},"410":{"description":"Quote expired"}}}},"/v1/trade/swaps":{"get":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"responses":{"200":{"description":"Authenticated identity swap history"}}}},"/v1/trade/swaps/{swapId}":{"get":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_SwapId"}],"responses":{"200":{"description":"Swap"}}}},"/v1/trade/swaps/{swapId}/status":{"get":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_SwapId"}],"responses":{"200":{"description":"Verified lifecycle status"}}}},"/v1/trade/solana/wallets/challenges":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"requestBody":{"$ref":"#/components/requestBodies/trade_SolanaWalletChallenge"},"responses":{"201":{"description":"Message to sign (Ed25519)"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"}}}},"/v1/trade/solana/wallets/verify":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"requestBody":{"$ref":"#/components/requestBodies/trade_SolanaWalletVerification"},"responses":{"201":{"description":"Wallet linked to authenticated identity via base58 Ed25519 signature"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"}}}},"/v1/trade/solana/swaps/preview":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"requestBody":{"$ref":"#/components/requestBodies/trade_SolanaSwap"},"responses":{"201":{"description":"Indicative preview without a swap transaction"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"},"422":{"$ref":"#/components/responses/trade_TradeRejected"}}}},"/v1/trade/solana/swaps/quote":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_IdempotencyKey"}],"requestBody":{"$ref":"#/components/requestBodies/trade_SolanaSwap"},"responses":{"201":{"description":"Unsigned Solana swap transaction (base64) for gas-sponsor"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"},"422":{"$ref":"#/components/responses/trade_TradeRejected"}}}},"/v1/trade/solana/swaps/verify":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_SolanaSignature"}],"responses":{"200":{"description":"On-chain status for the submitted Solana transaction"},"401":{"$ref":"#/components/responses/trade_Unauthorized"},"403":{"$ref":"#/components/responses/trade_Forbidden"}}}},"/v1/trade/solana/swaps/{swapId}/submissions":{"post":{"tags":["trade"],"security":[{"trade_bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/trade_SwapId"}],"requestBody":{"$ref":"#/components/requestBodies/trade_SolanaSubmission"},"responses":{"201":{"description":"Sponsored Solana transaction signature registered for worker confirmation"},"400":{"$ref":"#/components/responses/trade_ValidationError"},"404":{"$ref":"#/components/responses/trade_SwapNotFound"},"410":{"description":"Quote expired"}}}},"/v1/trade/admin/tokens":{"get":{"tags":["trade"],"security":[{"trade_adminApiKey":[]}],"responses":{"200":{"description":"Token registry"}}}},"/v1/trade/admin/tokens/{address}/block":{"post":{"tags":["trade"],"security":[{"trade_adminApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"201":{"description":"Token blocked and audited"}}}},"/v1/trade/admin/tokens/{address}/unblock":{"post":{"tags":["trade"],"security":[{"trade_adminApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"201":{"description":"Manual block removed; risk reassessment still required"}}}},"/v1/trade/admin/tokens/{address}/status":{"patch":{"tags":["trade"],"security":[{"trade_adminApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/trade_Address"}],"responses":{"200":{"description":"Token trading status updated and audited"}}}},"/v1/trade/admin/swaps":{"get":{"tags":["trade"],"security":[{"trade_adminApiKey":[]}],"responses":{"200":{"description":"All swaps"}}}},"/v1/trade/admin/swaps/{swapId}":{"get":{"tags":["trade"],"security":[{"trade_adminApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/trade_SwapId"}],"responses":{"200":{"description":"Swap and executions"}}}},"/v1/world-street-vault/health":{"get":{"summary":"Service health","tags":["world-street-vault"],"responses":{"200":{"description":"ok"}}}},"/v1/world-street-vault/config":{"get":{"summary":"Owner-tunable contract parameters","description":"Every value here is settable on-chain by the contract owner and HAS changed since deployment (minStartStake twice, the timer once, the split once). Read them from here and never hard-code them. Cached ~30s.","tags":["world-street-vault"],"responses":{"200":{"description":"Config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/world-street-vault_ConfigResponse"}}}}}}},"/v1/world-street-vault/players/{address}":{"get":{"summary":"One wallet: pending payout and lifetime figures","description":"pendingWei is the contract pendingWithdrawals(address) — a payout settle() could not push, which the player collects with claim(). Read live from the chain, so this one request replaces a per-block poll.","tags":["world-street-vault"],"parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player"},"400":{"description":"Malformed address"}}}},"/v1/world-street-vault/transactions":{"post":{"summary":"Hand the service a transaction hash the wallet just sent","description":"Answers 202 with the outcome as currently known, so a caller that submits after the transaction already mined gets the resolved answer without polling. Retires client-side receipt polling and GameStarted log decoding.","tags":["world-street-vault"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["hash"],"properties":{"hash":{"type":"string","example":"0xabc..."}}}}}},"responses":{"202":{"description":"Accepted, with the outcome so far"},"400":{"description":"Malformed hash"}}}},"/v1/world-street-vault/transactions/{hash}":{"get":{"summary":"What a submitted transaction turned out to be","description":"status: pending | confirmed | failed. action: started | joined | settled | claimed | unknown, with gameId where the action has one. An unknown hash is indistinguishable from one still in the mempool, so both read as pending.","tags":["world-street-vault"],"parameters":[{"name":"hash","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Outcome"},"400":{"description":"Malformed hash"}}}},"/v1/world-street-vault/games":{"get":{"summary":"List games — the lobby (and history)","description":"Defaults to the live lobby. Tops itself up from the contract when the indexer trails the chain head, so a game a player has just paid for is listed within one confirmation. Keyset-paginated: pass the returned nextCursor back as cursor. An UNKNOWN query parameter is a 400, never silently ignored.","tags":["world-street-vault"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["active","settled","all"],"default":"active"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Active games","content":{"application/json":{"schema":{"$ref":"#/components/schemas/world-street-vault_GamesResponse"}}}}}}},"/v1/world-street-vault/games/{id}":{"get":{"summary":"Get one game by its on-chain id","description":"Reads the index; on a miss for a valid id it falls through to the contract, so a game that exists on-chain is never 404ed for indexer lag. 404 only when the id has never been started.","tags":["world-street-vault"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Game","content":{"application/json":{"schema":{"$ref":"#/components/schemas/world-street-vault_GameResponse"}}}},"404":{"description":"Game not found"}}}},"/v1/world-street-vault/games/{id}/activities":{"get":{"summary":"One game's own activity feed","tags":["world-street-vault"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"ok"}}}},"/v1/world-street-vault/game/winners":{"get":{"summary":"Recent winners (settled games)","description":"Each row carries the full split (toWinner, toStarter, toTreasury) AND paidToWinner — what the winning wallet actually received. The contract pays the starter share to the winner own wallet when they started the game, so display paidToWinner, not toWinner. Keyset-paginated.","tags":["world-street-vault"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"ok"}}}},"/v1/world-street-vault/game/activities":{"get":{"summary":"Recent activity feed (started/joined/won), newest first in on-chain order","description":"Ordered by true chain position (block, log index), not DB insert time. Filter to one game with gameId, page with limit + cursor. NOTE: on a won row, amountWei is the WINNER SHARE ALONE; for what the wallet actually received use paidToWinner on GET /game/winners.","tags":["world-street-vault"],"parameters":[{"name":"gameId","in":"query","schema":{"type":"integer","minimum":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"ok"}}}},"/v1/perp/health":{"get":{"summary":"Service health","tags":["perp"],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_HealthResponse"}}}}}}},"/v1/perp/waitlist":{"post":{"summary":"Join the perp marketing waitlist","description":"Records an email for pre-launch marketing. Idempotent per email: a repeat signup returns 200 with `alreadyJoined: true` instead of an error. New signups fire `perp.waitlist.joined`.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_JoinWaitlistRequest"}}}},"responses":{"200":{"description":"Email was already on the waitlist (idempotent repeat)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_WaitlistJoinResponse"}}}},"201":{"description":"Email added to the waitlist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_WaitlistJoinResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Waitlist datastore unavailable (retryable)"}}},"get":{"summary":"List waitlist signups (ADMIN — emails are PII)","description":"Operator-only listing of collected emails, newest first. Requires the WAITLIST_ADMIN_KEY as a bearer token (use Authorize). Returns 404 when no admin key is configured on the service.","tags":["perp"],"security":[{"perp_waitlistAdminKey":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Page size."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Rows to skip (paging)."}],"responses":{"200":{"description":"One page of signups plus the total count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_WaitlistListResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"401":{"description":"Missing or wrong admin bearer key (UNAUTHORIZED)"},"404":{"description":"Listing disabled — no WAITLIST_ADMIN_KEY configured"},"502":{"description":"Waitlist datastore unavailable (retryable)"}}}},"/v1/perp/waitlist/{email}":{"delete":{"summary":"Remove an email from the waitlist (ADMIN)","description":"Operator-only removal (test data, unsubscribe requests). URL-encode the address (trader%40example.com). Requires the WAITLIST_ADMIN_KEY as a bearer token.","tags":["perp"],"security":[{"perp_waitlistAdminKey":[]}],"parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","format":"email"},"example":"trader@example.com","description":"The email to remove (normalized server-side)."}],"responses":{"200":{"description":"Email removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_WaitlistDeleteResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"401":{"description":"Missing or wrong admin bearer key (UNAUTHORIZED)"},"404":{"description":"Email not on the waitlist, or no WAITLIST_ADMIN_KEY configured"},"502":{"description":"Waitlist datastore unavailable (retryable)"}}}},"/v1/perp/ark/wallet/{address}":{"get":{"summary":"Get-or-create the perp wallet for an address","description":"Perp has no auth system of its own — the wallet address IS the identity. Every prepare/submit call needs the internal walletId this returns.","tags":["perp"],"parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The wallet row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_WalletResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"}}}},"/v1/perp/ark/assets":{"get":{"summary":"List active tradable assets","tags":["perp"],"responses":{"200":{"description":"Cached asset metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_AssetListResponse"}}}}}}},"/v1/perp/ark/prices":{"get":{"summary":"Live mid prices for every asset","tags":["perp"],"responses":{"200":{"description":"{ [symbol]: midPriceString }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArkPricesResponse"}}}},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/market-contexts":{"get":{"summary":"Live market stats for every active asset (mark, 24h change basis, funding, volume, open interest)","description":"One upstream market-data call, joined to the active asset cache by assetIndex — the trading UI's market list data source.","tags":["perp"],"responses":{"200":{"description":"Array of per-asset market stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_MarketContextListResponse"}}}},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/funding-history/{symbol}":{"get":{"summary":"Market-wide funding-rate history for one asset","description":"Not a wallet's own funding payments — the raw per-sample funding rate the venue published for this market. Drives the trading UI's Funding chart. endTime unset means \"through now\".","tags":["perp"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"startTime","in":"query","required":true,"schema":{"type":"integer"}},{"name":"endTime","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Array of funding samples, oldest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_FundingHistoryResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/candles/{symbol}":{"get":{"summary":"OHLCV candles for one asset","description":"Verified live against the venue's own candle snapshot — t is the OPEN time, T is the close time; v is total volume in the base asset, never USD. Drives the trading UI's chart. endTime unset means \"through now\".","tags":["perp"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"interval","in":"query","required":true,"schema":{"type":"string","enum":["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d","3d","1w","1M"]}},{"name":"startTime","in":"query","required":true,"schema":{"type":"integer"}},{"name":"endTime","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Array of candles, oldest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_CandlesResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/account-state/{address}":{"get":{"summary":"A wallet's live margin/balance state","tags":["perp"],"parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Live margin summary, withdrawable balance, and open positions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_AccountStateResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/arbitrum-balance/{address}":{"get":{"summary":"A wallet's live Arbitrum USDC balance","description":"Reads the destination chain directly rather than the Dextopus-webhook-driven treasury ledger — the frontend polls this to confirm a Base deposit actually landed, since a webhook can be missed, delayed, or (in local development) unreachable.","tags":["perp"],"parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Live balance, decimal string","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArbitrumBalanceResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Arbitrum RPC unavailable (retryable)"}}}},"/v1/perp/ark/wallets/{walletId}/positions":{"get":{"summary":"A wallet's open positions with live valuation","tags":["perp"],"parameters":[{"name":"walletId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Open positions with mark price and unrealized PnL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArkPositionListResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"}}}},"/v1/perp/ark/wallets/{walletId}/orders":{"get":{"summary":"A wallet's orders","tags":["perp"],"parameters":[{"name":"walletId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Orders, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArkOrderListResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"}}}},"/v1/perp/ark/wallets/{walletId}/positions/closed":{"get":{"summary":"A wallet's closed positions — trading history","description":"Closed positions only, newest closed first — open positions are never included (see /ark/wallets/{walletId}/positions for those). No live valuation: everything about a closed position is already final.","tags":["perp"],"parameters":[{"name":"walletId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Closed positions, newest closed first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArkClosedPositionListResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"}}}},"/v1/perp/ark/orders/prepare":{"post":{"summary":"Prepare an order (entry, optionally batched with TP/SL) for the client to sign","description":"Validates the request and available margin, and returns an unsigned action for the CLIENT to sign with its own embedded wallet — this backend holds no signing key of any kind (see src/signing/README.md). `reduceOnly: true` is set on both the take-profit and stop-loss legs. Throws with `details.reason: \"insufficient_margin\"` if the balance is short — bridge via /ark/bridge/prepare first and retry. Not yet the live trading path — see the service README's rebuild status note.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PlaceOrderRequest"}}}},"responses":{"200":{"description":"Unsigned action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedOrderResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/orders/submit":{"post":{"summary":"Submit a client-signed order action","description":"Recovers the real signer from the signature and rejects a mismatch with the claimed wallet before relaying the order onward. `prepared` is echoed back verbatim from /ark/orders/prepare.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitOrderRequest"}}}},"responses":{"201":{"description":"Order(s) submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PlaceOrderResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/leverage/prepare":{"post":{"summary":"Prepare a leverage/margin-mode update for the client to sign","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareLeverageRequest"}}}},"responses":{"200":{"description":"Unsigned action for the client to sign, or { alreadySet: true } if unchanged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedLeverageResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/leverage/submit":{"post":{"summary":"Submit a client-signed leverage update","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitLeverageRequest"}}}},"responses":{"200":{"description":"Leverage updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_UpdatedResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/orders/cancel/prepare":{"post":{"summary":"Prepare cancelling a resting order for the client to sign","description":"The order must already carry an externalOrderId (set once it has been acknowledged as resting or filled) — an order still in flight has nothing to cancel by id yet.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareCancelOrderRequest"}}}},"responses":{"200":{"description":"Unsigned cancel action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedCancelResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/orders/cancel/submit":{"post":{"summary":"Submit a client-signed cancel action","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitCancelOrderRequest"}}}},"responses":{"200":{"description":"Order cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArkOrderResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/positions/close/prepare":{"post":{"summary":"Prepare manually closing an open position for the client to sign","description":"Builds a single reduce-only IOC order in the opposite direction, sized to the position (or a smaller partial-close size). Does NOT check margin — closing frees margin, it never consumes it.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareClosePositionRequest"}}}},"responses":{"200":{"description":"Unsigned reduce-only order action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedClosePositionResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/positions/close/submit":{"post":{"summary":"Submit a client-signed manual close","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitClosePositionRequest"}}}},"responses":{"201":{"description":"Close order submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ClosePositionResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/orders/trigger/prepare":{"post":{"summary":"Prepare a standalone TP or SL trigger order for the client to sign","description":"Adds a new take-profit or stop-loss to an already-open position, or replaces one: there is no in-place \"modify\" action, so replacing an existing trigger is the caller's job — cancel the old one via /ark/orders/cancel first, then call this for the new one.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareTriggerOrderRequest"}}}},"responses":{"200":{"description":"Unsigned reduce-only trigger order action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedTriggerOrderResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/orders/trigger/submit":{"post":{"summary":"Submit a client-signed TP/SL trigger order","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitTriggerOrderRequest"}}}},"responses":{"201":{"description":"Trigger order submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ArkOrderResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/bridge/prepare":{"post":{"summary":"Prepare an Arbitrum -> trading balance bridge deposit","description":"The bridge deposit is a real EVM transaction — the one action in this flow that needs gas. Returns unsigned calldata (sized to the wallet's full Arbitrum USDC balance) for the client to send itself via its own sponsored-EVM flow (EIP-7702 + Alchemy); this backend never submits it. Returns `{ needed: false }` if the trading balance already covers the amount.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareBridgeRequest"}}}},"responses":{"200":{"description":"Unsigned calldata for the client to send, or { needed: false }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedBridgeResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/bridge/confirm":{"post":{"summary":"Record a broadcast bridge deposit and start confirmation polling","description":"Called once the client has already sent the sponsored transfer itself and knows its tx hash. Records the deposit and polls the trading balance until it is credited.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ConfirmBridgeRequest"}}}},"responses":{"202":{"description":"Deposit recorded and queued for confirmation polling","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_BridgeResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/dex-transfer/prepare":{"post":{"tags":["perp"],"summary":"Prepare a native -> HIP-3 dex margin transfer (sendAsset)","description":"Each HIP-3 dex margins as a separate Hyperliquid account: native USDC cannot back an equities/forex order until it is transferred to that dex's own balance. Returns an unsigned EIP-712 sendAsset action (no gas, off-chain) for the client to sign; destination is always the wallet's own address.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletId","destinationDex","amountUsdc"],"properties":{"walletId":{"type":"string"},"destinationDex":{"type":"string","example":"xyz"},"amountUsdc":{"type":"string","example":"10.5"}}}}}},"responses":{"200":{"description":"Unsigned sendAsset action + nonce"},"400":{"description":"Unknown wallet, empty dex, or amount above the free native balance"}}}},"/v1/perp/ark/dex-transfer/submit":{"post":{"tags":["perp"],"summary":"Submit a signed native -> HIP-3 dex margin transfer","description":"Verifies the signature really came from the wallet and that the destination is the wallet's own address, then relays to Hyperliquid. Instant; no gas.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletId","action","signature"],"properties":{"walletId":{"type":"string"},"action":{"type":"object"},"signature":{"type":"object"}}}}}},"responses":{"200":{"description":"Transferred"},"400":{"description":"Signature mismatch or invalid action"}}}},"/v1/perp/ark/withdrawals/prepare":{"post":{"summary":"Prepare a trading-balance -> Arbitrum withdrawal for the client to sign","description":"Checks the wallet's free withdrawable balance and returns an unsigned withdraw3 action. This is an off-chain signed message, not an EVM transaction — no gas involved.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareWithdrawalRequest"}}}},"responses":{"200":{"description":"Unsigned withdraw3 action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedWithdrawalResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/withdrawals/submit":{"post":{"summary":"Submit a client-signed withdrawal","description":"Recovers the real signer and verifies the destination is the wallet's own address (this platform never routes a withdrawal anywhere else) before relaying it onward and queueing confirmation polling.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitWithdrawalRequest"}}}},"responses":{"202":{"description":"Withdrawal accepted and queued for confirmation polling","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_WithdrawalResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/wallets/{walletId}/withdrawals/pending":{"get":{"summary":"A withdrawal that landed on Arbitrum but never finished forwarding to Base","description":"Lets the client resume a withdrawal's last hop after a page reload or a poll timeout — see WithdrawalService.getPendingWithdrawal. data is null when there is nothing to resume.","tags":["perp"],"parameters":[{"name":"walletId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The most recent unresolved withdrawal, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PendingWithdrawalResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/wallets/{walletId}/builder-fee":{"get":{"summary":"A wallet's builder-fee approval status","description":"The max builder fee (tenths of a basis point) the wallet has already approved for the platform treasury, and whether it covers what orders currently attach — see PERPS_BUILDER_FEE_TENTHS_BPS. approved: false means every order this wallet places carries no builder fee at all (an order that attaches an unapproved fee is rejected outright, so TradingService omits it rather than risk that).","tags":["perp"],"parameters":[{"name":"walletId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Builder-fee approval status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_BuilderFeeStatusResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/builder-fee/prepare":{"post":{"summary":"Prepare a builder-fee approval for the client to sign","description":"Returns an unsigned approveBuilderFee action granting the platform treasury a fee up to the protocol cap (0.1% on perps) — a one-time, user-signed EIP-712 action, the same family as withdraw3. Off-chain signed message, not an EVM transaction — no gas involved.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareBuilderFeeApprovalRequest"}}}},"responses":{"200":{"description":"Unsigned approveBuilderFee action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedBuilderFeeApprovalResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Builder fee collection is not configured, or service unavailable"}}}},"/v1/perp/ark/builder-fee/submit":{"post":{"summary":"Submit a client-signed builder-fee approval","description":"Recovers the real signer and verifies the approved builder is the platform treasury (never routes an approval anywhere else) before relaying it onward.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitBuilderFeeApprovalRequest"}}}},"responses":{"202":{"description":"Builder-fee approval accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_BuilderFeeApprovalResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/wallets/{walletId}/abstraction-mode":{"get":{"summary":"A wallet's account-abstraction mode","description":"The wallet's current mode (disabled/unifiedAccount/portfolioMargin) and whether that mode is eligible to collect builder fees — the venue requires disabled (Manual/Standard) mode for that.","tags":["perp"],"parameters":[{"name":"walletId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Account-abstraction mode status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_AbstractionModeStatusResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/abstraction-mode/prepare":{"post":{"summary":"Prepare an account-abstraction-mode change for the client to sign","description":"Returns an unsigned userSetAbstraction action — a user-signed EIP-712 action, the same family as approveBuilderFee/withdraw3. Off-chain signed message, not an EVM transaction — no gas involved.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PrepareAbstractionModeRequest"}}}},"responses":{"200":{"description":"Unsigned userSetAbstraction action for the client to sign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_PreparedAbstractionModeResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/abstraction-mode/submit":{"post":{"summary":"Submit a client-signed account-abstraction-mode change","description":"Recovers the real signer and verifies it matches the wallet requesting the change before relaying it onward.","tags":["perp"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_SubmitAbstractionModeRequest"}}}},"responses":{"202":{"description":"Account-abstraction-mode change accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_AbstractionModeChangeResponse"}}}},"400":{"$ref":"#/components/responses/perp_BadRequest"},"502":{"description":"Service unavailable (retryable)"}}}},"/v1/perp/ark/admin/rewards":{"get":{"summary":"Accrued builder-fee revenue (ADMIN)","description":"The treasury's accrued Hyperliquid builder-fee revenue — unclaimed, already-claimed, and total. Hyperliquid accrues this in its own referral-program state, separately from the treasury's spendable clearinghouseState balance; unclaimedRewards only becomes spendable once claimed via POST /ark/admin/rewards/claim. Requires the PERPS_ADMIN_KEY as a bearer token (use Authorize). Returns 404 when no admin key is configured on the service.","tags":["perp"],"security":[{"perp_perpsAdminKey":[]}],"responses":{"200":{"description":"Accrued reward totals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_RewardsStatusResponse"}}}},"401":{"description":"Missing or wrong admin bearer key (UNAUTHORIZED)"},"404":{"description":"Disabled — no PERPS_ADMIN_KEY configured"},"502":{"description":"Service unavailable, OR reward tracking not configured (no PERPS_TREASURY_ADDRESS)"}}}},"/v1/perp/ark/admin/rewards/claim":{"post":{"summary":"Claim all accrued builder-fee revenue (ADMIN)","description":"Signs and submits Hyperliquid's claimRewards action with the treasury's OWN key (PERPS_TREASURY_PRIVATE_KEY) — the one exception to this service never holding a signing key, since a claim is the platform claiming its own revenue, not a user action. Claims WHATEVER has accrued (no partial-amount claims); returns the fresh post-claim status. Requires the PERPS_ADMIN_KEY as a bearer token. Returns 404 when no admin key is configured.","tags":["perp"],"security":[{"perp_perpsAdminKey":[]}],"responses":{"200":{"description":"Post-claim reward totals","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_RewardsStatusResponse"}}}},"401":{"description":"Missing or wrong admin bearer key (UNAUTHORIZED)"},"404":{"description":"Disabled — no PERPS_ADMIN_KEY configured"},"502":{"description":"Service unavailable, OR claiming not configured (no PERPS_TREASURY_ADDRESS / PERPS_TREASURY_PRIVATE_KEY)"}}}},"/v1/chess/analysis/queue":{"get":{"tags":["chess"],"operationId":"get_analysis_queue","parameters":[{"name":"limit","in":"query","description":"Limit of queued/running jobs to list.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Queued and running analysis jobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_AnalysisQueueResponse"}}}}}}},"/v1/chess/arenas":{"get":{"tags":["chess"],"operationId":"list_arenas","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Arena tournaments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaListResponse"}}}}}},"post":{"tags":["chess"],"operationId":"create_arena","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateArenaRequest"}}},"required":true},"responses":{"200":{"description":"Arena tournament created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaSummaryResponse"}}}}}}},"/v1/chess/arenas/{id}":{"get":{"tags":["chess"],"operationId":"get_arena","parameters":[{"name":"player","in":"query","required":false,"schema":{"type":"string"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Arena tournament detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaResponse"}}}}}}},"/v1/chess/arenas/{id}/join":{"post":{"tags":["chess"],"operationId":"join_arena","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_JoinArenaRequest"}}},"required":true},"responses":{"200":{"description":"Player joined the Arena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaResponse"}}}}}}},"/v1/chess/arenas/{id}/start":{"post":{"tags":["chess"],"operationId":"start_arena","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_StartArenaRequest"}}},"required":true},"responses":{"200":{"description":"Arena started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaResponse"}}}}}}},"/v1/chess/arenas/{id}/withdraw":{"post":{"tags":["chess"],"operationId":"withdraw_arena","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaPlayerRequest"}}},"required":true},"responses":{"200":{"description":"Player withdrew or paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ArenaResponse"}}}}}}},"/v1/chess/betting/bets":{"post":{"tags":["chess"],"operationId":"place_bet","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlaceBetRequest"}}},"required":true},"responses":{"200":{"description":"Bet placed and stake escrowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_BetResponse"}}}}}}},"/v1/chess/betting/markets/{matchId}/bets":{"get":{"tags":["chess"],"operationId":"get_bettor_bets","parameters":[{"name":"matchId","in":"path","description":"Match id","required":true,"schema":{"type":"string"}},{"name":"bettor","in":"query","description":"Bettor wallet address","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"A bettor's bets on the match","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/chess_BetResponse"}}}}}}}},"/v1/chess/betting/markets/{matchId}/odds":{"get":{"tags":["chess"],"operationId":"get_market_odds","parameters":[{"name":"matchId","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Live pools and pari-mutuel odds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MarketOddsResponse"}}}}}}},"/v1/chess/betting/swiss/{swissId}/bets":{"get":{"tags":["chess"],"operationId":"get_swiss_bets","parameters":[{"name":"swissId","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}},{"name":"bettor","in":"query","description":"Bettor wallet address","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"A spectator's tournament bets","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/chess_SwissBetResponse"}}}}}}},"post":{"tags":["chess"],"operationId":"place_swiss_bet","parameters":[{"name":"swissId","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlaceSwissBetRequest"}}},"required":true},"responses":{"200":{"description":"Tournament winner bet placed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissBetResponse"}}}}}}},"/v1/chess/betting/swiss/{swissId}/odds":{"get":{"tags":["chess"],"operationId":"get_swiss_odds","parameters":[{"name":"swissId","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tournament winner pools and odds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissMarketOddsResponse"}}}}}}},"/v1/chess/cashier/config":{"get":{"tags":["chess"],"operationId":"get_cashier_config","responses":{"200":{"description":"Cashier chain + deposit configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CashierConfigResponse"}}}}}}},"/v1/chess/cashier/deposits/confirm":{"post":{"tags":["chess"],"operationId":"confirm_deposit","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ConfirmDepositRequest"}}},"required":true},"responses":{"200":{"description":"Deposit confirmed and credited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DepositResponse"}}}}}}},"/v1/chess/cashier/gas-health":{"get":{"tags":["chess"],"operationId":"get_gas_health","responses":{"200":{"description":"Gasless payout rail dry-run probe (no funds moved)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_GasHealthResponse"}}}}}}},"/v1/chess/cashier/players/{player}/balance":{"get":{"tags":["chess"],"operationId":"get_player_balance","parameters":[{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player cashier balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerBalanceResponse"}}}}}}},"/v1/chess/cashier/withdrawals":{"post":{"tags":["chess"],"operationId":"create_withdrawal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateWithdrawalRequest"}}},"required":true},"responses":{"200":{"description":"Withdrawal broadcast","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_WithdrawalResponse"}}}}}}},"/v1/chess/coach/catalog":{"get":{"tags":["chess"],"operationId":"get_coach_catalog","responses":{"200":{"description":"Versioned chess lesson catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachCatalogResponse"}}}}}}},"/v1/chess/coach/lessons/{lesson_key}/chapters/{chapter_key}/attempt":{"post":{"tags":["chess"],"operationId":"attempt_coach_lesson","parameters":[{"name":"lesson_key","in":"path","description":"Catalog lesson key","required":true,"schema":{"type":"string"}},{"name":"chapter_key","in":"path","description":"Catalog chapter key","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachLessonAttemptRequest"}}},"required":true},"responses":{"200":{"description":"Server-validated lesson attempt and durable progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachLessonAttemptResponse"}}}}}}},"/v1/chess/computer/matches":{"post":{"tags":["chess"],"operationId":"create_computer_match","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateComputerMatchRequest"}}},"required":true},"responses":{"200":{"description":"Casual Stockfish match created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/computer/matches/{id}/coach":{"get":{"tags":["chess"],"operationId":"get_computer_coach_state","parameters":[{"name":"id","in":"path","description":"Computer match id","required":true,"schema":{"type":"string"}},{"name":"player","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Durable live-coach state for the current ply","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ComputerCoachStateResponse"}}}}}}},"/v1/chess/computer/matches/{id}/coach/continue":{"post":{"tags":["chess"],"operationId":"continue_computer_coach_review","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachReviewActionRequest"}}},"required":true},"responses":{"200":{"description":"Release a reviewed move so the computer can reply","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachMoveAttemptResponse"}}}}}}},"/v1/chess/computer/matches/{id}/coach/hint":{"post":{"tags":["chess"],"operationId":"request_computer_coach_hint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachHintRequest"}}},"required":true},"responses":{"200":{"description":"Next progressive hint for the current position","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachHintResponse"}}}}}}},"/v1/chess/computer/matches/{id}/coach/move":{"post":{"tags":["chess"],"operationId":"request_computer_coach_move","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachMoveAttemptRequest"}}},"required":true},"responses":{"200":{"description":"Move committed and paused for a durable server-side review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachMoveAttemptResponse"}}}}}}},"/v1/chess/computer/matches/{id}/coach/undo":{"post":{"tags":["chess"],"operationId":"undo_computer_coach_review","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachReviewActionRequest"}}},"required":true},"responses":{"200":{"description":"Rewind the human move held for coach review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachMoveAttemptResponse"}}}}}}},"/v1/chess/computer/matches/{id}/hint":{"post":{"tags":["chess"],"operationId":"request_computer_hint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RequestComputerHintRequest"}}},"required":true},"responses":{"200":{"description":"Stockfish hint for an unstaked computer game","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ComputerHintResponse"}}}}}}},"/v1/chess/draughts/analysis/queue":{"get":{"tags":["chess"],"operationId":"get_analysis_queue","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsAnalysisQueueResponse"}}}}}}},"/v1/chess/draughts/betting/bets":{"post":{"tags":["chess"],"operationId":"place_bet","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlaceDraughtsBetRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsBetResponse"}}}}}}},"/v1/chess/draughts/betting/markets/{matchId}/bets":{"get":{"tags":["chess"],"operationId":"get_bets","parameters":[{"name":"matchId","in":"path","required":true,"schema":{"type":"string"}},{"name":"bettor","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsBetResponse"}}}}}}}},"/v1/chess/draughts/betting/markets/{matchId}/odds":{"get":{"tags":["chess"],"operationId":"get_odds","parameters":[{"name":"matchId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsMarketOddsResponse"}}}}}}},"/v1/chess/draughts/coach/catalog":{"get":{"tags":["chess"],"operationId":"get_catalog","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachCatalogResponse"}}}}}}},"/v1/chess/draughts/coach/lessons/{lesson_key}/chapters/{chapter_key}/attempt":{"post":{"tags":["chess"],"operationId":"attempt_lesson","parameters":[{"name":"lesson_key","in":"path","required":true,"schema":{"type":"string"}},{"name":"chapter_key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachLessonAttemptRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachLessonAttemptResponse"}}}}}}},"/v1/chess/draughts/computer/matches":{"post":{"tags":["chess"],"operationId":"create_computer_match","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateDraughtsComputerMatchRequest"}}},"required":true},"responses":{"200":{"description":"Draughts computer match created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/computer/matches/{id}/coach":{"get":{"tags":["chess"],"operationId":"get_state","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"player","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachStateResponse"}}}}}}},"/v1/chess/draughts/computer/matches/{id}/coach/continue":{"post":{"tags":["chess"],"operationId":"continue_review","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachReviewActionRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachMoveAttemptResponse"}}}}}}},"/v1/chess/draughts/computer/matches/{id}/coach/hint":{"post":{"tags":["chess"],"operationId":"hint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachHintRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachHintResponse"}}}}}}},"/v1/chess/draughts/computer/matches/{id}/coach/move":{"post":{"tags":["chess"],"operationId":"make_move","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachMoveAttemptRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachMoveAttemptResponse"}}}}}}},"/v1/chess/draughts/computer/matches/{id}/coach/undo":{"post":{"tags":["chess"],"operationId":"undo_review","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachReviewActionRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachMoveAttemptResponse"}}}}}}},"/v1/chess/draughts/computer/matches/{id}/hint":{"post":{"tags":["chess"],"operationId":"request_computer_hint","parameters":[{"name":"id","in":"path","description":"Draughts computer match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RequestDraughtsComputerHintRequest"}}},"required":true},"responses":{"200":{"description":"Draughts engine hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsComputerHintResponse"}}}}}}},"/v1/chess/draughts/matches":{"get":{"tags":["chess"],"operationId":"list_matches","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Draughts matches (lobby / spectator list)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchListResponse"}}}}}},"post":{"tags":["chess"],"operationId":"create_match","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CreateMatchRequest"}}},"required":true},"responses":{"200":{"description":"Draughts challenge created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}":{"get":{"tags":["chess"],"operationId":"get_match","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Draughts match state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/abort":{"post":{"tags":["chess"],"operationId":"abort","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Waiting game aborted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/analysis":{"get":{"tags":["chess"],"operationId":"get_match_analysis","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsAnalysisResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/analysis/request":{"post":{"tags":["chess"],"operationId":"request_match_analysis","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RequestDraughtsAnalysisRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsAnalysisResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/chat":{"get":{"tags":["chess"],"operationId":"list_match_chat_messages","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}},{"name":"room","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_draughts.MatchChatRoom"}},{"name":"player","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Draughts match chat history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchChatMessagesResponse"}}}}}},"post":{"tags":["chess"],"operationId":"create_match_chat_message","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CreateMatchChatMessageRequest"}}},"required":true},"responses":{"200":{"description":"Chat line accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchChatMessageResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/claim-draw":{"post":{"tags":["chess"],"operationId":"claim_draw","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Draw claimed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/claim-timeout":{"post":{"tags":["chess"],"operationId":"claim_timeout","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Timeout claimed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/comments":{"get":{"tags":["chess"],"operationId":"list_match_comments","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}},{"name":"ply","in":"query","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Persistent draughts match comments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchCommentsResponse"}}}}}},"post":{"tags":["chess"],"operationId":"set_match_comment","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.UpsertMatchCommentRequest"}}},"required":true},"responses":{"200":{"description":"Comment created or updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchCommentResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/comments/{comment_id}":{"delete":{"tags":["chess"],"operationId":"delete_match_comment","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}},{"name":"comment_id","in":"path","description":"Comment id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.DeleteMatchCommentRequest"}}},"required":true},"responses":{"200":{"description":"Comment deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchCommentResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/draw-offer":{"post":{"tags":["chess"],"operationId":"offer_draw","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Draw offered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/draw-response":{"post":{"tags":["chess"],"operationId":"respond_draw","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.DrawResponseRequest"}}},"required":true},"responses":{"200":{"description":"Draw offer accepted or declined","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/join":{"post":{"tags":["chess"],"operationId":"join_match","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.JoinMatchRequest"}}},"required":true},"responses":{"200":{"description":"Opponent joined; draughts game started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/moves":{"get":{"tags":["chess"],"operationId":"list_moves","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Move history (PDN-ready)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MovesResponse"}}}}}},"post":{"tags":["chess"],"operationId":"make_move","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MakeMoveRequest"}}},"required":true},"responses":{"200":{"description":"Move applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MoveResultResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/note":{"get":{"tags":["chess"],"operationId":"get_match_note","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}},{"name":"player","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Private note for this draughts match and viewer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchNoteResponse"}}}}}},"put":{"tags":["chess"],"operationId":"set_match_note","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.SetMatchNoteRequest"}}},"required":true},"responses":{"200":{"description":"Private note saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchNoteResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/pdn":{"get":{"tags":["chess"],"operationId":"get_pdn","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Game as a PDN document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PdnResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/rematch":{"post":{"tags":["chess"],"operationId":"rematch","parameters":[{"name":"id","in":"path","description":"Finished draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Offer or accept a rematch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/rematch-decline":{"post":{"tags":["chess"],"operationId":"rematch_decline","parameters":[{"name":"id","in":"path","description":"Finished draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Decline a rematch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/resign":{"post":{"tags":["chess"],"operationId":"resign","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Player resigned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/takeback":{"post":{"tags":["chess"],"operationId":"takeback","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Offer or accept a takeback","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/takeback-decline":{"post":{"tags":["chess"],"operationId":"takeback_decline","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Decline a takeback","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/matches/{id}/time-extension":{"post":{"tags":["chess"],"operationId":"extend_match_time","parameters":[{"name":"id","in":"path","description":"Draughts match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.ExtendMatchTimeRequest"}}},"required":true},"responses":{"200":{"description":"Both clocks extended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}}}}},"/v1/chess/draughts/players/{player}/coach-progress":{"get":{"tags":["chess"],"operationId":"get_coach_progress","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsCoachProgressResponse"}}}}}},"put":{"tags":["chess"],"operationId":"update_coach_progress","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_UpdateDraughtsCoachProgressRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsCoachProgressItemResponse"}}}}}}},"/v1/chess/draughts/players/{player}/coach/home":{"get":{"tags":["chess"],"operationId":"get_home","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachHomeResponse"}}}}}}},"/v1/chess/draughts/players/{player}/coach/profile":{"put":{"tags":["chess"],"operationId":"update_profile","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.UpdateCoachProfileRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachProfileResponse"}}}}}}},"/v1/chess/draughts/players/{player}/coach/training":{"get":{"tags":["chess"],"operationId":"get_training","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"player","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachTrainingResponse"}}}}}}},"/v1/chess/draughts/players/{player}/coach/training/{match_id}/{ply}/attempt":{"post":{"tags":["chess"],"operationId":"attempt_training","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}},{"name":"match_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"ply","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachTrainingAttemptRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.CoachTrainingAttemptResponse"}}}}}}},"/v1/chess/draughts/players/{player}/insights":{"get":{"tags":["chess"],"operationId":"get_player_insights","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DraughtsInsightsResponse"}}}}}}},"/v1/chess/draughts/players/{player}/matches":{"get":{"tags":["chess"],"operationId":"player_matches","parameters":[{"name":"player","in":"path","description":"Wallet / player id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Draughts match history for a player","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_draughts.MatchListResponse"}}}}}}},"/v1/chess/draughts/players/{player}/ratings":{"get":{"tags":["chess"],"operationId":"get_player_ratings","parameters":[{"name":"player","in":"path","description":"Player wallet","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Draughts ratings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerRatingsResponse"}}}}}}},"/v1/chess/draughts/players/{player}/ratings/{perf}/history":{"get":{"tags":["chess"],"operationId":"get_player_rating_history","parameters":[{"name":"player","in":"path","description":"Player wallet","required":true,"schema":{"type":"string"}},{"name":"perf","in":"path","description":"Draughts performance key","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Draughts rating history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerRatingHistoryResponse"}}}}}}},"/v1/chess/fair-play/reviews":{"get":{"tags":["chess"],"operationId":"list_fair_play_reviews","parameters":[{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_FairPlayReviewStatus"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Moderator fair-play review queue","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_FairPlayReviewListResponse"}}}}}}},"/v1/chess/fair-play/reviews/{id}":{"get":{"tags":["chess"],"operationId":"get_fair_play_review","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Detailed fair-play evidence","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_FairPlayReviewDetailResponse"}}}}}}},"/v1/chess/fair-play/reviews/{id}/resolve":{"post":{"tags":["chess"],"operationId":"resolve_fair_play_review","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ResolveFairPlayReviewRequest"}}},"required":true},"responses":{"200":{"description":"Resolved fair-play review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_FairPlayReviewDetailResponse"}}}}}}},"/v1/chess/health":{"get":{"tags":["chess"],"summary":"Liveness probe. Reports process uptime without touching dependencies.","operationId":"health_check","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_HealthStatus"}}}}}}},"/v1/chess/leaderboard":{"get":{"tags":["chess"],"operationId":"get_rating_leaderboard","parameters":[{"name":"perf","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_PerfKey"}},{"name":"country","in":"query","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Active established players ranked by speed bucket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RatingLeaderboardResponse"}}}}}}},"/v1/chess/leaderboard/countries":{"get":{"tags":["chess"],"operationId":"get_rating_leaderboard_countries","parameters":[{"name":"perf","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_PerfKey"}}],"responses":{"200":{"description":"Countries represented by active established players","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RatingLeaderboardCountriesResponse"}}}}}}},"/v1/chess/leaderboard/rules":{"get":{"tags":["chess"],"operationId":"get_rating_leaderboard_rules","responses":{"200":{"description":"Authoritative rating and leaderboard thresholds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RatingLeaderboardRulesResponse"}}}}}}},"/v1/chess/leaderboard/stats":{"get":{"tags":["chess"],"operationId":"get_rating_pool_stats","parameters":[{"name":"perf","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_PerfKey"}},{"name":"country","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Active rating-pool and live-game statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RatingPoolStatsResponse"}}}}}}},"/v1/chess/lottery/config":{"get":{"tags":["chess"],"operationId":"get_lottery_config","responses":{"200":{"description":"Immutable lottery rules and runtime sales configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryConfigResponse"}}}}}}},"/v1/chess/lottery/draws/current":{"get":{"tags":["chess"],"operationId":"get_current_lottery_draw","responses":{"200":{"description":"Current automated lottery draw","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryDrawResponse"}}}}}}},"/v1/chess/lottery/draws/results":{"get":{"tags":["chess"],"operationId":"get_completed_lottery_draws","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64"}}],"responses":{"200":{"description":"Settled draw history, newest first","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryDrawResponse"}}}}}}}},"/v1/chess/lottery/draws/{id}":{"get":{"tags":["chess"],"operationId":"get_lottery_draw","parameters":[{"name":"id","in":"path","description":"Draw id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Lottery draw","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryDrawResponse"}}}}}}},"/v1/chess/lottery/draws/{id}/check":{"post":{"tags":["chess"],"operationId":"check_lottery_plays","parameters":[{"name":"id","in":"path","description":"Settled draw id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CheckLotteryPlaysRequest"}}},"required":true},"responses":{"200":{"description":"Read-only result check for one or more ticket combinations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CheckLotteryPlaysResponse"}}}}}}},"/v1/chess/lottery/draws/{id}/quick-pick":{"post":{"tags":["chess"],"operationId":"create_lottery_quick_pick","parameters":[{"name":"id","in":"path","description":"Open draw id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_QuickPickRequest"}}},"required":true},"responses":{"200":{"description":"Securely generated ticket combinations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_QuickPickResponse"}}}}}}},"/v1/chess/lottery/draws/{id}/result":{"get":{"tags":["chess"],"operationId":"get_lottery_result","parameters":[{"name":"id","in":"path","description":"Draw id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Committed draw result and verifiable randomness proof","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryDrawResultResponse"}}}}}}},"/v1/chess/lottery/draws/{id}/tickets":{"post":{"tags":["chess"],"operationId":"purchase_lottery_ticket","parameters":[{"name":"id","in":"path","description":"Open draw id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PurchaseLotteryTicketRequest"}}},"required":true},"responses":{"200":{"description":"Purchased immutable lottery ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryTicketResponse"}}}}}}},"/v1/chess/lottery/players/{player}/eligibility":{"get":{"tags":["chess"],"operationId":"get_lottery_eligibility","parameters":[{"name":"player","in":"path","description":"Authenticated wallet","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player lottery purchase eligibility","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryEligibilityResponse"}}}}}}},"/v1/chess/lottery/players/{player}/tickets":{"get":{"tags":["chess"],"operationId":"get_player_lottery_tickets","parameters":[{"name":"player","in":"path","description":"Authenticated wallet","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64"}}],"responses":{"200":{"description":"Player lottery ticket history","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryTicketResponse"}}}}}}}},"/v1/chess/lottery/tickets/{id}":{"get":{"tags":["chess"],"operationId":"get_lottery_ticket","parameters":[{"name":"id","in":"path","description":"Ticket id","required":true,"schema":{"type":"string"}},{"name":"player","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player-owned lottery ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_LotteryTicketResponse"}}}}}}},"/v1/chess/matches":{"get":{"tags":["chess"],"operationId":"list_matches","parameters":[{"name":"status","in":"query","description":"Filter by lifecycle status (waiting | active | finished | aborted).","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum rows to return (default 50, capped at 100).","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Matches (lobby / spectator list)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchListResponse"}}}}}},"post":{"tags":["chess"],"operationId":"create_match","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateMatchHttpRequest"}}},"required":true},"responses":{"200":{"description":"Challenge created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}":{"get":{"tags":["chess"],"operationId":"get_match","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Match state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/abort":{"post":{"tags":["chess"],"operationId":"abort","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Match aborted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/analysis":{"get":{"tags":["chess"],"operationId":"get_match_analysis","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stored post-game engine analysis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchAnalysisResponse"}}}}}}},"/v1/chess/matches/{id}/analysis/request":{"post":{"tags":["chess"],"operationId":"request_match_analysis","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RequestMatchAnalysisRequest"}}},"required":true},"responses":{"200":{"description":"Analysis was queued or already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchAnalysisResponse"}}}}}}},"/v1/chess/matches/{id}/chat":{"get":{"tags":["chess"],"operationId":"list_match_chat_messages","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}},{"name":"room","in":"query","description":"Chat room to read; spectator chat is the public default.","required":false,"schema":{"$ref":"#/components/schemas/chess_MatchChatRoom"}},{"name":"player","in":"query","description":"Optional authenticated actor for the private player room. When the\ntrusted proxy sends `x-wallet-address`, that header wins.","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum rows to return (default 50, capped at 100).","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Match chat history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchChatMessagesResponse"}}}}}},"post":{"tags":["chess"],"operationId":"create_match_chat_message","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateMatchChatMessageRequest"}}},"required":true},"responses":{"200":{"description":"Chat line accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchChatMessageResponse"}}}}}}},"/v1/chess/matches/{id}/claim-draw":{"post":{"tags":["chess"],"operationId":"claim_draw","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Draw claimed (threefold / fifty-move)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/claim-timeout":{"post":{"tags":["chess"],"operationId":"claim_timeout","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Opponent flagged on time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/comments":{"get":{"tags":["chess"],"operationId":"list_match_comments","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}},{"name":"ply","in":"query","description":"Optional ply filter. `0` is the starting position, `1` the first move,\netc. Omit to fetch all comments.","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Persistent match comments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchCommentsResponse"}}}}}},"post":{"tags":["chess"],"operationId":"set_match_comment","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_UpsertMatchCommentRequest"}}},"required":true},"responses":{"200":{"description":"Comment created or updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchCommentResponse"}}}}}}},"/v1/chess/matches/{id}/comments/{comment_id}":{"delete":{"tags":["chess"],"operationId":"delete_match_comment","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}},{"name":"comment_id","in":"path","description":"Comment id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DeleteMatchCommentRequest"}}},"required":true},"responses":{"200":{"description":"Comment deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchCommentResponse"}}}}}}},"/v1/chess/matches/{id}/draw-offer":{"post":{"tags":["chess"],"operationId":"offer_draw","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Draw offered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/draw-response":{"post":{"tags":["chess"],"operationId":"respond_draw","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_DrawResponseRequest"}}},"required":true},"responses":{"200":{"description":"Draw offer answered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/fair-play":{"get":{"tags":["chess"],"operationId":"get_match_fair_play_status","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}},{"name":"player","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player-safe fair-play status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_FairPlayMatchStatusResponse"}}}}}}},"/v1/chess/matches/{id}/join":{"post":{"tags":["chess"],"operationId":"join_match","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_JoinMatchRequest"}}},"required":true},"responses":{"200":{"description":"Opponent joined; game started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/moves":{"get":{"tags":["chess"],"operationId":"list_moves","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Move history (PGN-ready)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MovesResponse"}}}}}},"post":{"tags":["chess"],"operationId":"make_move","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MakeMoveRequest"}}},"required":true},"responses":{"200":{"description":"Move applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MoveResultResponse"}}}}}}},"/v1/chess/matches/{id}/note":{"get":{"tags":["chess"],"operationId":"get_match_note","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}},{"name":"player","in":"query","description":"Optional viewer identity. In production the trusted\n`x-wallet-address` header becomes authoritative when present.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Private note for this match and viewer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchNoteResponse"}}}}}},"put":{"tags":["chess"],"operationId":"set_match_note","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SetMatchNoteRequest"}}},"required":true},"responses":{"200":{"description":"Private note saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchNoteResponse"}}}}}}},"/v1/chess/matches/{id}/pgn":{"get":{"tags":["chess"],"operationId":"get_pgn","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Game as a PGN document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PgnResponse"}}}}}}},"/v1/chess/matches/{id}/rematch":{"post":{"tags":["chess"],"operationId":"rematch","parameters":[{"name":"id","in":"path","description":"Finished match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Offer or accept a Lila-style rematch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/rematch-decline":{"post":{"tags":["chess"],"operationId":"rematch_decline","parameters":[{"name":"id","in":"path","description":"Finished match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Cancel or decline a pending rematch offer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/resign":{"post":{"tags":["chess"],"operationId":"resign","parameters":[{"name":"id","in":"path","description":"Match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Player resigned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/takeback":{"post":{"tags":["chess"],"operationId":"takeback","parameters":[{"name":"id","in":"path","description":"Active match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Offer or accept a Lila-style takeback","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/takeback-decline":{"post":{"tags":["chess"],"operationId":"takeback_decline","parameters":[{"name":"id","in":"path","description":"Active match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerActionRequest"}}},"required":true},"responses":{"200":{"description":"Cancel or decline a pending takeback offer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/time-extension":{"post":{"tags":["chess"],"operationId":"extend_match_time","parameters":[{"name":"id","in":"path","description":"Active casual match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ExtendMatchTimeRequest"}}},"required":true},"responses":{"200":{"description":"Purchased time added to both clocks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchResponse"}}}}}}},"/v1/chess/matches/{id}/video/token":{"post":{"tags":["chess"],"operationId":"issue_match_video_token","parameters":[{"name":"id","in":"path","description":"Video-enabled match id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchVideoTokenRequest"}}},"required":true},"responses":{"200":{"description":"Short-lived game-scoped Ark Stream token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchVideoTokenResponse"}}}},"401":{"description":"Authenticated wallet required"},"409":{"description":"Video is disabled or the room is closed"},"503":{"description":"Ark Stream is not configured"}}}},"/v1/chess/players/{player}/coach-progress":{"get":{"tags":["chess"],"operationId":"get_coach_progress","parameters":[{"name":"player","in":"path","description":"Wallet or player id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stored coach and lesson progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachProgressResponse"}}}}}},"put":{"tags":["chess"],"operationId":"upsert_coach_progress","parameters":[{"name":"player","in":"path","description":"Wallet or player id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_UpsertCoachProgressRequest"}}},"required":true},"responses":{"200":{"description":"Progress was upserted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachProgressResponse"}}}}}}},"/v1/chess/players/{player}/coach/home":{"get":{"tags":["chess"],"operationId":"get_coach_home","parameters":[{"name":"player","in":"path","description":"Authenticated player","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Onboarding profile, points, lesson locks, recommendation, and training count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachHomeResponse"}}}}}}},"/v1/chess/players/{player}/coach/profile":{"put":{"tags":["chess"],"operationId":"update_coach_profile","parameters":[{"name":"player","in":"path","description":"Authenticated player","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_UpdateCoachProfileRequest"}}},"required":true},"responses":{"200":{"description":"Updated coach onboarding preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachProfileResponse"}}}}}}},"/v1/chess/players/{player}/coach/training":{"get":{"tags":["chess"],"operationId":"get_coach_training","parameters":[{"name":"player","in":"path","description":"Wallet or player id","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of recent mistakes to return, from 1 to 50.","required":false,"schema":{"type":["integer","null"],"format":"int64"}}],"responses":{"200":{"description":"Recent analyzed mistakes converted to practice positions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachTrainingResponse"}}}}}}},"/v1/chess/players/{player}/coach/training/{match_id}/{ply}/attempt":{"post":{"tags":["chess"],"operationId":"attempt_coach_training","parameters":[{"name":"player","in":"path","description":"Authenticated player","required":true,"schema":{"type":"string"}},{"name":"match_id","in":"path","description":"Source analysed match","required":true,"schema":{"type":"string"}},{"name":"ply","in":"path","description":"Source mistake ply","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachTrainingAttemptRequest"}}},"required":true},"responses":{"200":{"description":"Server-validated mistake-practice attempt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CoachTrainingAttemptResponse"}}}}}}},"/v1/chess/players/{player}/insights":{"get":{"tags":["chess"],"operationId":"get_player_insights","parameters":[{"name":"player","in":"path","description":"Wallet or player id","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum buckets to return per dimension.","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Derived weakness profile from analysed matches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_WeaknessProfileResponse"}}}}}}},"/v1/chess/players/{player}/matches":{"get":{"tags":["chess"],"operationId":"player_matches","parameters":[{"name":"status","in":"query","description":"Filter by lifecycle status (waiting | active | finished | aborted).","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum rows to return (default 50, capped at 100).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"A player's match history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_MatchListResponse"}}}}}}},"/v1/chess/players/{player}/product-access":{"get":{"tags":["chess"],"operationId":"get_product_access","parameters":[{"name":"player","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player coaching and usage access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ProductAccessResponse"}}}}}}},"/v1/chess/players/{player}/rating-onboarding":{"put":{"tags":["chess"],"operationId":"update_rating_onboarding","parameters":[{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_UpdateRatingOnboardingRequest"}}},"required":true},"responses":{"200":{"description":"Selected starting rating tier","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_RatingOnboardingResponse"}}}},"409":{"description":"Starting tier is locked by rated activity"}}}},"/v1/chess/players/{player}/ratings":{"get":{"tags":["chess"],"operationId":"get_player_ratings","parameters":[{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Current ratings by perf bucket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerRatingsResponse"}}}}}}},"/v1/chess/players/{player}/ratings/{perf}/chart":{"get":{"tags":["chess"],"operationId":"get_player_rating_chart","parameters":[{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}},{"name":"perf","in":"path","description":"Concrete speed bucket","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_RatingChartRange"}}],"responses":{"200":{"description":"Chronological graph-ready rating points","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerRatingChartResponse"}}}}}}},"/v1/chess/players/{player}/ratings/{perf}/history":{"get":{"tags":["chess"],"operationId":"get_player_rating_history","parameters":[{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}},{"name":"perf","in":"path","description":"Perf key","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Rating history for one perf bucket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerRatingHistoryResponse"}}}}}}},"/v1/chess/players/{player}/ratings/{perf}/stats":{"get":{"tags":["chess"],"operationId":"get_player_rating_stats","parameters":[{"name":"player","in":"path","description":"Wallet address","required":true,"schema":{"type":"string"}},{"name":"perf","in":"path","description":"Concrete speed bucket","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Player rating, record, extremes, rank, and percentile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PlayerRatingStatsResponse"}}}}}}},"/v1/chess/products":{"get":{"tags":["chess"],"operationId":"get_product_catalog","responses":{"200":{"description":"Chess product catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ProductCatalogResponse"}}}}}}},"/v1/chess/products/purchase":{"post":{"tags":["chess"],"operationId":"purchase_product","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PurchaseProductRequest"}}},"required":true},"responses":{"200":{"description":"Idempotent product purchase","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ProductPurchaseResponse"}}}}}}},"/v1/chess/puzzles/catalog":{"get":{"tags":["chess"],"operationId":"catalog_stats","responses":{"200":{"description":"Imported puzzle catalog statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PuzzleCatalogStatsResponse"}}}}}}},"/v1/chess/puzzles/next":{"get":{"tags":["chess"],"operationId":"next_puzzle","parameters":[{"name":"player","in":"query","description":"Solver identity used to avoid already-completed puzzles.","required":false,"schema":{"type":["string","null"]}},{"name":"rating","in":"query","description":"Desired puzzle rating. Defaults to 1200.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"theme","in":"query","description":"Optional exact Lichess theme key, for example `fork` or `mateIn2`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Next unsolved puzzle","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PuzzleResponse"}}}}}}},"/v1/chess/puzzles/{id}":{"get":{"tags":["chess"],"operationId":"get_puzzle","parameters":[{"name":"id","in":"path","description":"Lichess puzzle id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Puzzle position without its hidden solution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PuzzleResponse"}}}}}}},"/v1/chess/puzzles/{id}/attempt":{"post":{"tags":["chess"],"operationId":"attempt_puzzle","parameters":[{"name":"id","in":"path","description":"Lichess puzzle id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PuzzleAttemptRequest"}}},"required":true},"responses":{"200":{"description":"Validated puzzle move and continuation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_PuzzleAttemptResponse"}}}}}}},"/v1/chess/ready":{"get":{"tags":["chess"],"summary":"Dependency readiness probe. A process may remain live while it is removed\nfrom service discovery until Postgres and the configured broker recover.","operationId":"readiness_check","responses":{"200":{"description":"Service dependencies are ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ReadinessStatus"}}}},"503":{"description":"A required dependency is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_ReadinessStatus"}}}}}}},"/v1/chess/swiss":{"get":{"tags":["chess"],"operationId":"list_swiss","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/chess_SwissFormat"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Swiss tournaments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissListResponse"}}}}}},"post":{"tags":["chess"],"operationId":"create_swiss","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_CreateSwissRequest"}}},"required":true},"responses":{"200":{"description":"Swiss tournament created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissSummaryResponse"}}}}}}},"/v1/chess/swiss/{id}":{"get":{"tags":["chess"],"operationId":"get_swiss","parameters":[{"name":"id","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Swiss tournament detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissResponse"}}}}}}},"/v1/chess/swiss/{id}/join":{"post":{"tags":["chess"],"operationId":"join_swiss","parameters":[{"name":"id","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_JoinSwissRequest"}}},"required":true},"responses":{"200":{"description":"Player joined","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissResponse"}}}}}}},"/v1/chess/swiss/{id}/reconcile":{"post":{"tags":["chess"],"operationId":"reconcile_swiss","parameters":[{"name":"id","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_StartNextRoundRequest"}}},"required":true},"responses":{"200":{"description":"Reconciled ongoing swiss pairings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissResponse"}}}}}}},"/v1/chess/swiss/{id}/rounds/next":{"post":{"tags":["chess"],"operationId":"start_next_round","parameters":[{"name":"id","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_StartNextRoundRequest"}}},"required":true},"responses":{"200":{"description":"Started the next swiss round","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissResponse"}}}}}}},"/v1/chess/swiss/{id}/withdraw":{"post":{"tags":["chess"],"operationId":"withdraw_swiss","parameters":[{"name":"id","in":"path","description":"Swiss tournament id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissPlayerRequest"}}},"required":true},"responses":{"200":{"description":"Player withdrawn or marked absent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/chess_SwissResponse"}}}}}}},"/v1/gas-sponsor/capabilities":{"get":{"tags":["gas-sponsor"],"operationId":"get_capabilities","responses":{"200":{"description":"Current scaffold capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/gas-sponsor_CapabilitiesResponse"}}}}}}},"/v1/gas-sponsor/health":{"get":{"tags":["gas-sponsor"],"operationId":"health_check","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/gas-sponsor_HealthStatus"}}}}}}},"/v1/gas-sponsor/solana/sponsor":{"post":{"tags":["gas-sponsor"],"operationId":"sponsor_solana","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/gas-sponsor_SolanaSponsorRequest"}}},"required":true},"responses":{"200":{"description":"Signs a Solana transaction with the configured sponsor wallet as fee payer; submits immediately when every other required signature is already present, otherwise returns a partially signed transaction for the client to finish","content":{"application/json":{"schema":{"$ref":"#/components/schemas/gas-sponsor_SolanaSponsorResponse"}}}}}}},"/v1/earn/health":{"get":{"operationId":"get__health","summary":"GET /health","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/openapi.json":{"get":{"operationId":"get__openapi_json","summary":"GET /openapi.json","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/me":{"get":{"operationId":"get__me","summary":"GET /me","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/check-name":{"get":{"operationId":"get__sponsors_check_name","summary":"GET /sponsors/check-name","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/check-slug":{"get":{"operationId":"get__sponsors_check_slug","summary":"GET /sponsors/check-slug","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/public/resolve":{"get":{"operationId":"get__sponsors_public_resolve","summary":"GET /sponsors/public/resolve","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/public/{slug}/stats":{"get":{"operationId":"get__sponsors_public_slug_stats","summary":"GET /sponsors/public/{slug}/stats","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/public/{slug}":{"get":{"operationId":"get__sponsors_public_slug_","summary":"GET /sponsors/public/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/create":{"post":{"operationId":"post__sponsors_create","summary":"POST /sponsors/create","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/setup":{"post":{"operationId":"post__sponsors_setup","summary":"POST /sponsors/setup","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/usersponsor-details":{"post":{"operationId":"post__sponsors_usersponsor_details","summary":"POST /sponsors/usersponsor-details","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/":{"get":{"operationId":"get__sponsors_","summary":"GET /sponsors/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/edit":{"post":{"operationId":"post__sponsors_edit","summary":"POST /sponsors/edit","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/list":{"get":{"operationId":"get__sponsors_list","summary":"GET /sponsors/list","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/stats":{"get":{"operationId":"get__sponsors_stats","summary":"GET /sponsors/stats","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsors/update-entity-name":{"post":{"operationId":"post__sponsors_update_entity_name","summary":"POST /sponsors/update-entity-name","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/check-name":{"get":{"operationId":"get__companies_check_name","summary":"GET /companies/check-name","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/check-slug":{"get":{"operationId":"get__companies_check_slug","summary":"GET /companies/check-slug","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/public/resolve":{"get":{"operationId":"get__companies_public_resolve","summary":"GET /companies/public/resolve","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/public/{slug}/stats":{"get":{"operationId":"get__companies_public_slug_stats","summary":"GET /companies/public/{slug}/stats","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/public/{slug}":{"get":{"operationId":"get__companies_public_slug_","summary":"GET /companies/public/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/create":{"post":{"operationId":"post__companies_create","summary":"POST /companies/create","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/setup":{"post":{"operationId":"post__companies_setup","summary":"POST /companies/setup","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/usersponsor-details":{"post":{"operationId":"post__companies_usersponsor_details","summary":"POST /companies/usersponsor-details","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/":{"get":{"operationId":"get__companies_","summary":"GET /companies/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/edit":{"post":{"operationId":"post__companies_edit","summary":"POST /companies/edit","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/list":{"get":{"operationId":"get__companies_list","summary":"GET /companies/list","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/stats":{"get":{"operationId":"get__companies_stats","summary":"GET /companies/stats","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/companies/update-entity-name":{"post":{"operationId":"post__companies_update_entity_name","summary":"POST /companies/update-entity-name","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/random-username":{"get":{"operationId":"get__user_random_username","summary":"GET /user/random-username","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/pfps":{"post":{"operationId":"post__user_pfps","summary":"POST /user/pfps","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/search":{"get":{"operationId":"get__user_search","summary":"GET /user/search","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/public/{username}/stats":{"get":{"operationId":"get__user_public_username_stats","summary":"GET /user/public/{username}/stats","tags":["earn"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/public/{username}":{"get":{"operationId":"get__user_public_username_","summary":"GET /user/public/{username}","tags":["earn"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/username":{"get":{"operationId":"get__user_username","summary":"GET /user/username","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/update":{"post":{"operationId":"post__user_update","summary":"POST /user/update","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/profile":{"get":{"operationId":"get__user_profile","summary":"GET /user/profile","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/complete-profile":{"post":{"operationId":"post__user_complete_profile","summary":"POST /user/complete-profile","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/update-email-settings":{"post":{"operationId":"post__user_update_email_settings","summary":"POST /user/update-email-settings","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/user/update-survey":{"post":{"operationId":"post__user_update_survey","summary":"POST /user/update-survey","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/grants/live":{"get":{"operationId":"get__grants_live","summary":"GET /grants/live","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/grants/{slug}":{"get":{"operationId":"get__grants_slug_","summary":"GET /grants/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/":{"get":{"operationId":"get__agents_","summary":"GET /agents/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}},"post":{"operationId":"post__agents_","summary":"POST /agents/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/claim-preview":{"get":{"operationId":"get__agents_claim_preview","summary":"GET /agents/claim-preview","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/status":{"get":{"operationId":"get__agents_status","summary":"GET /agents/status","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/comments/{id}":{"get":{"operationId":"get__agents_comments_id_","summary":"GET /agents/comments/{id}","tags":["earn"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/comments/create":{"post":{"operationId":"post__agents_comments_create","summary":"POST /agents/comments/create","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/listings/live":{"get":{"operationId":"get__agents_listings_live","summary":"GET /agents/listings/live","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/listings/details/{slug}":{"get":{"operationId":"get__agents_listings_details_slug_","summary":"GET /agents/listings/details/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/submissions/create":{"post":{"operationId":"post__agents_submissions_create","summary":"POST /agents/submissions/create","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/agents/submissions/update":{"post":{"operationId":"post__agents_submissions_update","summary":"POST /agents/submissions/update","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/ai-generate/title":{"post":{"operationId":"post__sponsor_dashboard_ai_generate_title","summary":"POST /sponsor-dashboard/ai-generate/title","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/ai-generate/questions":{"post":{"operationId":"post__sponsor_dashboard_ai_generate_questions","summary":"POST /sponsor-dashboard/ai-generate/questions","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/ai-generate/skills":{"post":{"operationId":"post__sponsor_dashboard_ai_generate_skills","summary":"POST /sponsor-dashboard/ai-generate/skills","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/ai-generate/rewards":{"post":{"operationId":"post__sponsor_dashboard_ai_generate_rewards","summary":"POST /sponsor-dashboard/ai-generate/rewards","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/live-opportunities":{"get":{"operationId":"get__listings_live_opportunities","summary":"GET /listings/live-opportunities","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/category-earnings":{"get":{"operationId":"get__listings_category_earnings","summary":"GET /listings/category-earnings","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/details/{slug}":{"get":{"operationId":"get__listings_details_slug_","summary":"GET /listings/details/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/submissions/{slug}":{"get":{"operationId":"get__listings_submissions_slug_","summary":"GET /listings/submissions/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/bookmarks":{"get":{"operationId":"get__listings_bookmarks","summary":"GET /listings/bookmarks","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/latest-active-slug":{"get":{"operationId":"get__listings_latest_active_slug","summary":"GET /listings/latest-active-slug","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/bookmark/status":{"get":{"operationId":"get__listings_bookmark_status","summary":"GET /listings/bookmark/status","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/bookmark/toggle":{"post":{"operationId":"post__listings_bookmark_toggle","summary":"POST /listings/bookmark/toggle","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/":{"get":{"operationId":"get__listings_","summary":"GET /listings/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/count":{"get":{"operationId":"get__listings_count","summary":"GET /listings/count","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/live":{"get":{"operationId":"get__listings_live","summary":"GET /listings/live","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/{listingId}/related":{"get":{"operationId":"get__listings_listingId_related","summary":"GET /listings/{listingId}/related","tags":["earn"],"parameters":[{"name":"listingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/{listingId}/submission-count":{"get":{"operationId":"get__listings_listingId_submission_count","summary":"GET /listings/{listingId}/submission-count","tags":["earn"],"parameters":[{"name":"listingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/listings/{listingId}/winners":{"get":{"operationId":"get__listings_listingId_winners","summary":"GET /listings/{listingId}/winners","tags":["earn"],"parameters":[{"name":"listingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/local-talent/":{"get":{"operationId":"get__sponsor_dashboard_local_talent_","summary":"GET /sponsor-dashboard/local-talent/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/leaderboard/":{"get":{"operationId":"get__leaderboard_","summary":"GET /leaderboard/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/chapters/":{"get":{"operationId":"get__chapters_","summary":"GET /chapters/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/chapters/{chapterId}/core-members":{"get":{"operationId":"get__chapters_chapterId_core_members","summary":"GET /chapters/{chapterId}/core-members","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"chapterId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/comment/create":{"post":{"operationId":"post__comment_create","summary":"POST /comment/create","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/comment/{id}":{"get":{"operationId":"get__comment_id_","summary":"GET /comment/{id}","tags":["earn"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/comment/{id}/pin":{"post":{"operationId":"post__comment_id_pin","summary":"POST /comment/{id}/pin","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/comment/{id}/delete":{"delete":{"operationId":"delete__comment_id_delete","summary":"DELETE /comment/{id}/delete","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/disputes/":{"post":{"operationId":"post__disputes_","summary":"POST /disputes/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/disputes/{id}/resolve":{"post":{"operationId":"post__disputes_id_resolve","summary":"POST /disputes/{id}/resolve","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/email/manual/support":{"post":{"operationId":"post__email_manual_support","summary":"POST /email/manual/support","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/email/manual/welcome-sponsor":{"post":{"operationId":"post__email_manual_welcome_sponsor","summary":"POST /email/manual/welcome-sponsor","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/email/unsubscribe":{"get":{"operationId":"get__email_unsubscribe","summary":"GET /email/unsubscribe","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}},"post":{"operationId":"post__email_unsubscribe","summary":"POST /email/unsubscribe","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/email/validate":{"post":{"operationId":"post__email_validate","summary":"POST /email/validate","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/email/webhook":{"post":{"operationId":"post__email_webhook","summary":"POST /email/webhook","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/feed/get":{"get":{"operationId":"get__feed_get","summary":"GET /feed/get","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/feed/{type}/{id}/get":{"get":{"operationId":"get__feed_type_id_get","summary":"GET /feed/{type}/{id}/get","tags":["earn"],"parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grant-application/ai/unreviewed":{"get":{"operationId":"get__sponsor_dashboard_grant_application_ai_unreviewed","summary":"GET /sponsor-dashboard/grant-application/ai/unreviewed","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grant-application/ai/review":{"post":{"operationId":"post__sponsor_dashboard_grant_application_ai_review","summary":"POST /sponsor-dashboard/grant-application/ai/review","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grant-application/ai/commit-reviewed":{"post":{"operationId":"post__sponsor_dashboard_grant_application_ai_commit_reviewed","summary":"POST /sponsor-dashboard/grant-application/ai/commit-reviewed","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/grant-application/get":{"get":{"operationId":"get__grant_application_get","summary":"GET /grant-application/get","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/grant-application/like":{"post":{"operationId":"post__grant_application_like","summary":"POST /grant-application/like","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/approved-grantees":{"get":{"operationId":"get__sponsor_dashboard_grants_approved_grantees","summary":"GET /sponsor-dashboard/grants/approved-grantees","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/add-tranche":{"post":{"operationId":"post__sponsor_dashboard_grants_add_tranche","summary":"POST /sponsor-dashboard/grants/add-tranche","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/update-tranche-status":{"post":{"operationId":"post__sponsor_dashboard_grants_update_tranche_status","summary":"POST /sponsor-dashboard/grants/update-tranche-status","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/update-label":{"post":{"operationId":"post__sponsor_dashboard_grants_update_label","summary":"POST /sponsor-dashboard/grants/update-label","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/update-notes":{"post":{"operationId":"post__sponsor_dashboard_grants_update_notes","summary":"POST /sponsor-dashboard/grants/update-notes","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/update-ship-progress":{"put":{"operationId":"put__sponsor_dashboard_grants_update_ship_progress","summary":"PUT /sponsor-dashboard/grants/update-ship-progress","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/{slug}/applications":{"get":{"operationId":"get__sponsor_dashboard_grants_slug_applications","summary":"GET /sponsor-dashboard/grants/{slug}/applications","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/{slug}/tranches":{"get":{"operationId":"get__sponsor_dashboard_grants_slug_tranches","summary":"GET /sponsor-dashboard/grants/{slug}/tranches","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/grants/{slug}":{"get":{"operationId":"get__sponsor_dashboard_grants_slug_","summary":"GET /sponsor-dashboard/grants/{slug}","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/grants/update/{id}":{"post":{"operationId":"post__grants_update_id_","summary":"POST /grants/update/{id}","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/grants/delete/{id}":{"post":{"operationId":"post__grants_delete_id_","summary":"POST /grants/delete/{id}","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/public-stats":{"get":{"operationId":"get__hackathon_public_stats","summary":"GET /hackathon/public-stats","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/talent-olympics/overview":{"get":{"operationId":"get__hackathon_talent_olympics_overview","summary":"GET /hackathon/talent-olympics/overview","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/stats":{"get":{"operationId":"get__hackathon_stats","summary":"GET /hackathon/stats","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/listings":{"get":{"operationId":"get__hackathon_listings","summary":"GET /hackathon/listings","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/list":{"get":{"operationId":"get__hackathon_list","summary":"GET /hackathon/list","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/subscribe/get":{"post":{"operationId":"post__hackathon_subscribe_get","summary":"POST /hackathon/subscribe/get","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/subscribe/toggle":{"post":{"operationId":"post__hackathon_subscribe_toggle","summary":"POST /hackathon/subscribe/toggle","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hackathon/{slug}":{"get":{"operationId":"get__hackathon_slug_","summary":"GET /hackathon/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/homepage/sponsor-count":{"get":{"operationId":"get__homepage_sponsor_count","summary":"GET /homepage/sponsor-count","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/homepage/user-count":{"get":{"operationId":"get__homepage_user_count","summary":"GET /homepage/user-count","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/homepage/feed":{"get":{"operationId":"get__homepage_feed","summary":"GET /homepage/feed","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/homepage/stats":{"get":{"operationId":"get__homepage_stats","summary":"GET /homepage/stats","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/homepage/recent-earners":{"get":{"operationId":"get__homepage_recent_earners","summary":"GET /homepage/recent-earners","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/image/sign":{"post":{"operationId":"post__image_sign","summary":"POST /image/sign","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/image/complete":{"post":{"operationId":"post__image_complete","summary":"POST /image/complete","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/image/delete":{"delete":{"operationId":"delete__image_delete","summary":"DELETE /image/delete","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/draft":{"post":{"operationId":"post__job_posts_draft","summary":"POST /job-posts/draft","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/{id}/publish":{"post":{"operationId":"post__job_posts_id_publish","summary":"POST /job-posts/{id}/publish","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/{id}/update":{"post":{"operationId":"post__job_posts_id_update","summary":"POST /job-posts/{id}/update","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/{id}/close":{"post":{"operationId":"post__job_posts_id_close","summary":"POST /job-posts/{id}/close","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/mine":{"get":{"operationId":"get__job_posts_mine","summary":"GET /job-posts/mine","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/":{"get":{"operationId":"get__job_posts_","summary":"GET /job-posts/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/job-posts/{slug}":{"get":{"operationId":"get__job_posts_slug_","summary":"GET /job-posts/{slug}","tags":["earn"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/proposals/":{"post":{"operationId":"post__proposals_","summary":"POST /proposals/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/proposals/{id}/withdraw":{"post":{"operationId":"post__proposals_id_withdraw","summary":"POST /proposals/{id}/withdraw","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/proposals/mine":{"get":{"operationId":"get__proposals_mine","summary":"GET /proposals/mine","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/proposals/for-job/{jobPostId}":{"get":{"operationId":"get__proposals_for_job_jobPostId_","summary":"GET /proposals/for-job/{jobPostId}","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"jobPostId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/proposals/{id}/shortlist":{"post":{"operationId":"post__proposals_id_shortlist","summary":"POST /proposals/{id}/shortlist","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/proposals/{id}/hire":{"post":{"operationId":"post__proposals_id_hire","summary":"POST /proposals/{id}/hire","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/contracts/mine":{"get":{"operationId":"get__contracts_mine","summary":"GET /contracts/mine","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/contracts/{id}":{"get":{"operationId":"get__contracts_id_","summary":"GET /contracts/{id}","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/contracts/{id}/complete":{"post":{"operationId":"post__contracts_id_complete","summary":"POST /contracts/{id}/complete","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/member-invites/accept":{"post":{"operationId":"post__member_invites_accept","summary":"POST /member-invites/accept","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/member-invites/send":{"post":{"operationId":"post__member_invites_send","summary":"POST /member-invites/send","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/member-invites/verify":{"get":{"operationId":"get__member_invites_verify","summary":"GET /member-invites/verify","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/":{"post":{"operationId":"post__milestones_","summary":"POST /milestones/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}},"get":{"operationId":"get__milestones_","summary":"GET /milestones/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/escrow-quote":{"get":{"operationId":"get__milestones_id_escrow_quote","summary":"GET /milestones/{id}/escrow-quote","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/escrow-status":{"get":{"operationId":"get__milestones_id_escrow_status","summary":"GET /milestones/{id}/escrow-status","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/fund":{"post":{"operationId":"post__milestones_id_fund","summary":"POST /milestones/{id}/fund","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/submit":{"post":{"operationId":"post__milestones_id_submit","summary":"POST /milestones/{id}/submit","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/approve":{"post":{"operationId":"post__milestones_id_approve","summary":"POST /milestones/{id}/approve","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/release":{"post":{"operationId":"post__milestones_id_release","summary":"POST /milestones/{id}/release","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/refund-quote":{"get":{"operationId":"get__milestones_id_refund_quote","summary":"GET /milestones/{id}/refund-quote","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/refund":{"post":{"operationId":"post__milestones_id_refund","summary":"POST /milestones/{id}/refund","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/milestones/{id}/claim":{"get":{"operationId":"get__milestones_id_claim","summary":"GET /milestones/{id}/claim","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/hello":{"get":{"operationId":"get__hello","summary":"GET /hello","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/location":{"get":{"operationId":"get__location","summary":"GET /location","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/twitter/tweet-stats":{"get":{"operationId":"get__twitter_tweet_stats","summary":"GET /twitter/tweet-stats","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor/verification":{"post":{"operationId":"post__sponsor_verification","summary":"POST /sponsor/verification","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/notifications/":{"get":{"operationId":"get__notifications_","summary":"GET /notifications/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/notifications/vapid-key":{"get":{"operationId":"get__notifications_vapid_key","summary":"GET /notifications/vapid-key","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/notifications/subscribe":{"post":{"operationId":"post__notifications_subscribe","summary":"POST /notifications/subscribe","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/notifications/unsubscribe":{"post":{"operationId":"post__notifications_unsubscribe","summary":"POST /notifications/unsubscribe","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/notifications/read":{"post":{"operationId":"post__notifications_read","summary":"POST /notifications/read","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/og/get":{"get":{"operationId":"get__og_get","summary":"GET /og/get","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/og/update":{"post":{"operationId":"post__og_update","summary":"POST /og/update","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/pow/get":{"get":{"operationId":"get__pow_get","summary":"GET /pow/get","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/pow/create":{"post":{"operationId":"post__pow_create","summary":"POST /pow/create","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/pow/edit":{"post":{"operationId":"post__pow_edit","summary":"POST /pow/edit","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/pow/like":{"post":{"operationId":"post__pow_like","summary":"POST /pow/like","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/ratings/":{"post":{"operationId":"post__ratings_","summary":"POST /ratings/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/ratings/for-user/{userId}":{"get":{"operationId":"get__ratings_for_user_userId_","summary":"GET /ratings/for-user/{userId}","tags":["earn"],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/search/{query}":{"get":{"operationId":"get__search_query_","summary":"GET /search/{query}","tags":["earn"],"parameters":[{"name":"query","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listings/is-create-allowed":{"get":{"operationId":"get__sponsor_dashboard_listings_is_create_allowed","summary":"GET /sponsor-dashboard/listings/is-create-allowed","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listings":{"get":{"operationId":"get__sponsor_dashboard_listings","summary":"GET /sponsor-dashboard/listings","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/active-hackathons":{"get":{"operationId":"get__sponsor_dashboard_active_hackathons","summary":"GET /sponsor-dashboard/active-hackathons","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/check-slug":{"get":{"operationId":"get__sponsor_dashboard_listing_check_slug","summary":"GET /sponsor-dashboard/listing/check-slug","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/total-payments-made":{"get":{"operationId":"get__sponsor_dashboard_listing_id_total_payments_made","summary":"GET /sponsor-dashboard/listing/{id}/total-payments-made","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/templates":{"get":{"operationId":"get__sponsor_dashboard_templates","summary":"GET /sponsor-dashboard/templates","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/templates/{slug}":{"get":{"operationId":"get__sponsor_dashboard_templates_slug_","summary":"GET /sponsor-dashboard/templates/{slug}","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/draft":{"post":{"operationId":"post__sponsor_dashboard_listing_draft","summary":"POST /sponsor-dashboard/listing/draft","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/escrow-quote":{"get":{"operationId":"get__sponsor_dashboard_listing_id_escrow_quote","summary":"GET /sponsor-dashboard/listing/{id}/escrow-quote","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/escrow-status":{"get":{"operationId":"get__sponsor_dashboard_listing_id_escrow_status","summary":"GET /sponsor-dashboard/listing/{id}/escrow-status","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/release":{"post":{"operationId":"post__sponsor_dashboard_listing_id_release","summary":"POST /sponsor-dashboard/listing/{id}/release","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/fund":{"post":{"operationId":"post__sponsor_dashboard_listing_id_fund","summary":"POST /sponsor-dashboard/listing/{id}/fund","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/publish":{"post":{"operationId":"post__sponsor_dashboard_listing_id_publish","summary":"POST /sponsor-dashboard/listing/{id}/publish","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/update":{"post":{"operationId":"post__sponsor_dashboard_listing_id_update","summary":"POST /sponsor-dashboard/listing/{id}/update","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/announce":{"post":{"operationId":"post__sponsor_dashboard_listing_id_announce","summary":"POST /sponsor-dashboard/listing/{id}/announce","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submission/add-payment":{"post":{"operationId":"post__sponsor_dashboard_submission_add_payment","summary":"POST /sponsor-dashboard/submission/add-payment","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/email-estimate":{"post":{"operationId":"post__sponsor_dashboard_listing_email_estimate","summary":"POST /sponsor-dashboard/listing/email-estimate","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/featured-posts":{"post":{"operationId":"post__sponsor_dashboard_listing_featured_posts","summary":"POST /sponsor-dashboard/listing/featured-posts","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listings/verify-external-payment":{"post":{"operationId":"post__sponsor_dashboard_listings_verify_external_payment","summary":"POST /sponsor-dashboard/listings/verify-external-payment","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/unpublish":{"post":{"operationId":"post__sponsor_dashboard_listing_id_unpublish","summary":"POST /sponsor-dashboard/listing/{id}/unpublish","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/listing/{id}/delete":{"delete":{"operationId":"delete__sponsor_dashboard_listing_id_delete","summary":"DELETE /sponsor-dashboard/listing/{id}/delete","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/{slug}/listing":{"get":{"operationId":"get__sponsor_dashboard_slug_listing","summary":"GET /sponsor-dashboard/{slug}/listing","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/{slug}/submissions":{"get":{"operationId":"get__sponsor_dashboard_slug_submissions","summary":"GET /sponsor-dashboard/{slug}/submissions","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/members/":{"get":{"operationId":"get__sponsor_dashboard_members_","summary":"GET /sponsor-dashboard/members/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/members/remove":{"post":{"operationId":"post__sponsor_dashboard_members_remove","summary":"POST /sponsor-dashboard/members/remove","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/members/update-role":{"post":{"operationId":"post__sponsor_dashboard_members_update_role","summary":"POST /sponsor-dashboard/members/update-role","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submission/reject":{"post":{"operationId":"post__sponsor_dashboard_submission_reject","summary":"POST /sponsor-dashboard/submission/reject","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submission/toggle-winner":{"post":{"operationId":"post__sponsor_dashboard_submission_toggle_winner","summary":"POST /sponsor-dashboard/submission/toggle-winner","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submission/update-label":{"post":{"operationId":"post__sponsor_dashboard_submission_update_label","summary":"POST /sponsor-dashboard/submission/update-label","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submission/update-notes":{"post":{"operationId":"post__sponsor_dashboard_submission_update_notes","summary":"POST /sponsor-dashboard/submission/update-notes","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submissions/ai/unreviewed":{"get":{"operationId":"get__sponsor_dashboard_submissions_ai_unreviewed","summary":"GET /sponsor-dashboard/submissions/ai/unreviewed","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sponsor-dashboard/submissions/ai/commit-reviewed":{"post":{"operationId":"post__sponsor_dashboard_submissions_ai_commit_reviewed","summary":"POST /sponsor-dashboard/submissions/ai/commit-reviewed","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/check":{"get":{"operationId":"get__submission_check","summary":"GET /submission/check","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/get":{"get":{"operationId":"get__submission_get","summary":"GET /submission/get","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/mine":{"get":{"operationId":"get__submission_mine","summary":"GET /submission/mine","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/claim":{"get":{"operationId":"get__submission_claim","summary":"GET /submission/claim","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/create":{"post":{"operationId":"post__submission_create","summary":"POST /submission/create","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/update":{"post":{"operationId":"post__submission_update","summary":"POST /submission/update","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/like":{"post":{"operationId":"post__submission_like","summary":"POST /submission/like","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/submission/kyc/verify-completion":{"get":{"operationId":"get__submission_kyc_verify_completion","summary":"GET /submission/kyc/verify-completion","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/sumsub/access-token":{"post":{"operationId":"post__sumsub_access_token","summary":"POST /sumsub/access-token","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/time-entries/":{"post":{"operationId":"post__time_entries_","summary":"POST /time-entries/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}},"get":{"operationId":"get__time_entries_","summary":"GET /time-entries/","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/time-entries/{id}/approve":{"post":{"operationId":"post__time_entries_id_approve","summary":"POST /time-entries/{id}/approve","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/time-entries/{id}/reject":{"post":{"operationId":"post__time_entries_id_reject","summary":"POST /time-entries/{id}/reject","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/time-entries/contract/{id}/bill":{"post":{"operationId":"post__time_entries_contract_id_bill","summary":"POST /time-entries/contract/{id}/bill","tags":["earn"],"security":[{"earn_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/tokens/icon":{"get":{"operationId":"get__tokens_icon","summary":"GET /tokens/icon","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/earn/tokens/":{"get":{"operationId":"get__tokens_","summary":"GET /tokens/","tags":["earn"],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/earn_ApiResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal error"}}}},"/v1/kash/health":{"get":{"summary":"Service health","tags":["kash"],"responses":{"200":{"description":"Service is healthy"}}}},"/v1/kash/desk":{"get":{"summary":"On-chain desk snapshot: chain id, contract addresses, price, pause state, reserve","description":"The single integration surface for on-chain buying/selling — the frontend never talks to the chain. 503 until KASH_SALE_ADDRESS/KASH_REDEEM_ADDRESS are configured.","tags":["kash"],"responses":{"200":{"description":"Desk info"},"503":{"description":"Desk not configured"}}}},"/v1/kash/desk/buy/quote":{"get":{"summary":"Price a buy: usdcAmount (decimal string) → KASH+ out (decimal + exact wei)","tags":["kash"],"parameters":[{"name":"usdcAmount","in":"query","required":true,"schema":{"type":"string"},"example":"70"}],"responses":{"200":{"description":"Quote"}}}},"/v1/kash/desk/sell/quote":{"get":{"summary":"Price a sell: kashAmount (decimal string) → USDC out, reserve and coverage","tags":["kash"],"parameters":[{"name":"kashAmount","in":"query","required":true,"schema":{"type":"string"},"example":"10"}],"responses":{"200":{"description":"Quote"}}}},"/v1/kash/desk/buy/prepare":{"post":{"summary":"Step 1 of a buy: the EIP-712 USDC-permit payload the wallet signs","description":"Returns typedData for eth_signTypedData_v4 (USDC domain \"USD Coin\"/\"2\", built server-side) plus the deadline and a quote. Sign it, then POST /desk/buy/tx. 409 while the sale desk is paused.","tags":["kash"],"responses":{"200":{"description":"Typed data to sign"},"409":{"description":"Desk paused"}}}},"/v1/kash/desk/buy/tx":{"post":{"summary":"Step 2 of a buy: the encoded { chainId, to, data } transaction the wallet submits","description":"Pass back the deadline from prepare and the 65-byte signature. minKashOutWei defaults to the live quote.","tags":["kash"],"responses":{"200":{"description":"Unsigned transaction"}}}},"/v1/kash/desk/sell/prepare":{"post":{"summary":"Step 1 of a sell: the EIP-712 KASH+-permit payload the wallet signs","description":"Returns typedData for eth_signTypedData_v4 — note the KASH+ permit domain is \"Kash\"/\"1\" (not the display name), built server-side so clients cannot get it wrong. 409 while the redeem desk is paused or the reserve cannot cover the payout.","tags":["kash"],"responses":{"200":{"description":"Typed data to sign"},"409":{"description":"Paused or reserve uncovered"}}}},"/v1/kash/desk/sell/tx":{"post":{"summary":"Step 2 of a sell: the encoded { chainId, to, data } transaction the wallet submits","tags":["kash"],"responses":{"200":{"description":"Unsigned transaction"}}}},"/v1/kash/purchases":{"post":{"externalDocs":{"description":"Settle the payment first: send usdcAmount of USDC from the buyer wallet to chain.paymentAddress (from GET /status), wait for the receipt, then POST that tx hash here. Verification requires from == wallet, so the buyer must sign the transfer themselves.","url":"https://basescan.org"},"summary":"Buy KSH with mock USDC (unlocks activity earning)","description":"Mints KSH at the current oracle price and credits the treasury with the USDC. Holding the resulting balance is what unlocks — and multiplies — activity earning.","tags":["kash"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_PurchaseRequest"}}}},"responses":{"201":{"description":"KSH purchased","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_PurchaseResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"},"409":{"description":"Sale allocation exhausted (CONFLICT)"},"502":{"description":"Price oracle unavailable or stale (retryable)"}}},"get":{"summary":"List purchases (optionally for one wallet)","tags":["kash"],"parameters":[{"name":"wallet","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":200,"default":50}}],"responses":{"200":{"description":"Purchases, newest first"}}}},"/v1/kash/purchases/quote":{"get":{"summary":"Preview KSH received for a USDC amount","tags":["kash"],"parameters":[{"name":"amount","in":"query","required":true,"schema":{"type":"string"},"example":"10"}],"responses":{"200":{"description":"Quote (no state change)"},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/activities/quote":{"get":{"summary":"Preview: a $X activity earns Y points ⇒ Z KSH at the current price","tags":["kash"],"parameters":[{"name":"amount","in":"query","required":true,"schema":{"type":"string"},"example":"100","description":"USD notional to preview."}],"responses":{"200":{"description":"Points, marginal breakdown, reward USD, KSH at current price"},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/subscriptions/tiers":{"get":{"summary":"Subscription catalogue (tier, monthly price)","tags":["kash"],"responses":{"200":{"description":"Tiers, ascending; tier 1 is the free default"}}}},"/v1/kash/subscriptions/{wallet}":{"get":{"summary":"A wallet's subscription: effective tier, expiry, active flag","tags":["kash"],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"example":"0x1111111111111111111111111111111111111111"}],"responses":{"200":{"description":"Subscription status (tier 1 when none or lapsed)"},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/subscriptions":{"post":{"summary":"Buy or extend a subscription tier","description":"The tier CAPS which volume-tier rate the wallet can earn at, so upgrading only pays off for a wallet whose volume already reaches past its cap. Tiers lapse at period end rather than auto-renewing. In real-USDC mode `paymentTxHash` must be a verified on-chain transfer to the treasury.","tags":["kash"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_SubscribeRequest"}}}},"responses":{"201":{"description":"Subscription active"},"400":{"$ref":"#/components/responses/kash_BadRequest"},"409":{"description":"An active higher tier is already in place (CONFLICT)"}}}},"/v1/kash/activities":{"post":{"summary":"Simulate a monetized activity (DEMO mode only)","description":"Accrues Kash + for a buy/sell/trade of the given USD notional exactly as a real broker event would. Returns 201 when a reward was applied and 200 with a `reason` when a guard blocked it (e.g. `locked` — the wallet holds no KSH). Disabled (404) when KASH_DEMO_MODE is false.","tags":["kash"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ActivityRequest"}}}},"responses":{"200":{"description":"No reward — see `reason`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_AccrualResponse"}}}},"201":{"description":"Reward accrued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_AccrualResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"},"401":{"description":"Operator bearer key required (real-money modes)"},"404":{"description":"Demo mode disabled"}}}},"/v1/kash/accounts/{wallet}":{"get":{"summary":"A wallet's Kash + standing: balance, tier, convertibility, progress","tags":["kash"],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"example":"0x1111111111111111111111111111111111111111"}],"responses":{"200":{"description":"Account profile (zeros for unknown wallets)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_AccountResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/accounts/{wallet}/ledger":{"get":{"summary":"A wallet's purchase/reward/conversion ledger (newest first)","tags":["kash"],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"example":"0x1111111111111111111111111111111111111111"},{"name":"limit","in":"query","schema":{"type":"integer","maximum":200,"default":50}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Ledger entries"},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/settlements/claim":{"post":{"summary":"Settle this wallet's points into KSH now","description":"Converts the caller's accrued points to KSH at the current price and mints them. Unlike POST /settlements/run — which prices an entire settlement period at one instant and needs the operator key — this claims only the named wallet, so it carries no admin key. The tradeoff is that the holder chooses the moment they are priced at. No on-chain event proves who is claiming, so `signature` must recover to `wallet` over the message `World Street — claim Kash settlement\\nwallet: <wallet, lowercased>\\nts: <timestamp>`, signed within 5 minutes of `timestamp`.","tags":["kash"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wallet","signature","timestamp"],"properties":{"wallet":{"type":"string","example":"0x1111111111111111111111111111111111111111"},"signature":{"type":"string","description":"65-byte personal_sign signature over the claim message","example":"0xababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab"},"timestamp":{"type":"integer","description":"Unix ms the message was signed at — must be within 5 minutes of now"}}}}}},"responses":{"201":{"description":"Settlement report — wallets, KSH minted, mint tx"},"400":{"$ref":"#/components/responses/kash_BadRequest"},"401":{"description":"Signature missing, expired, or does not match wallet"}}}},"/v1/kash/settlements/current":{"get":{"summary":"The live period: points accrued so far and what they would pay","description":"The settlement period currently accruing (KASH_SETTLEMENT_PERIOD_SECONDS, ~30 days by default). Its KSH figure is INDICATIVE — points are only priced at the settlement instant, so this moves with the oracle until then.","tags":["kash"],"responses":{"200":{"description":"Settlement-period summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_SettlementResponse"}}}}}}},"/v1/kash/settlements/{weekKey}":{"get":{"summary":"A specific settlement period, by the full ISO timestamp of its start","tags":["kash"],"parameters":[{"name":"weekKey","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"},"example":"2026-08-01T00:00:00.000Z"}],"responses":{"200":{"description":"Settlement-period summary — zeros for a period that never accrued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_SettlementResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/rail/debits":{"post":{"summary":"Settle a KASH payment for a sibling service (rail key + permit)","description":"The rail Market Square settles stream tickets, ARK Store orders and verification renewals through — none of which the calling service can settle itself, because it holds no balances. Requires TWO things and neither is sufficient alone: the rail key proves the CALLER is a trusted service, and the EIP-2612 permit proves the WALLET HOLDER agreed to this spend. A backend able to move a balance on its key alone would be custodial, which this platform is not (ADR-0005). A debit BURNS, because the KashController exposes mint/mintBatch/burn and no transfer — so in-app spends are a supply sink. Idempotent on idempotencyKey: a replay returns the ORIGINAL outcome, failures included, and never charges twice.","tags":["kash"],"security":[{"kash_railKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wallet","amountKash","reason","idempotencyKey"],"properties":{"wallet":{"type":"string","example":"0xabc..."},"amountKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"Decimal string, never a number — floats do not hold money."},"reason":{"type":"string","example":"ticket_purchase"},"idempotencyKey":{"type":"string","description":"The caller's own reference for this ONE movement. Must be unique per payment and stable across their retries."},"refType":{"type":"string","example":"ticket"},"refId":{"type":"string"},"permit":{"type":"object","description":"The holder's EIP-2612 consent, signed off-chain and gasless for them. Required in ethers mode for any wallet but the operator's own.","properties":{"deadline":{"type":"integer"},"v":{"type":"integer"},"r":{"type":"string"},"s":{"type":"string"}}}}}}}},"responses":{"201":{"description":"The settled debit"},"400":{"description":"VALIDATION_ERROR — malformed amount, or a zero payment"},"401":{"description":"Rail bearer key required"},"404":{"description":"KASH_RAIL_API_KEY unset — the rail is not enabled here"}}}},"/v1/kash/rail/debits/{idempotencyKey}":{"get":{"summary":"Look up a debit the caller is unsure about (rail key)","description":"Reconciliation for an in-doubt movement. Answers `{ found: false }` for an unknown key rather than 404, so a caller can tell \"this debit never landed\" (fail the order) apart from \"the route is not deployed\" (retry later). A bare 404 conflates the two, and the caller's next move is opposite in each case.","tags":["kash"],"security":[{"kash_railKey":[]}],"parameters":[{"name":"idempotencyKey","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The debit, or { found: false }"},"401":{"description":"Rail bearer key required"},"404":{"description":"KASH_RAIL_API_KEY unset"}}}},"/v1/kash/rail/refunds":{"post":{"summary":"Give a confirmed debit back (rail key)","description":"MINTS, because the debit burned — the pair nets to zero against supply, which is what keeps the sink honest. Only a confirmed debit can be refunded: refunding a failed one would mint tokens that were never burned. Idempotent — refunding twice returns the same row rather than minting again.","tags":["kash"],"security":[{"kash_railKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["railRef"],"properties":{"railRef":{"type":"string"}}}}}},"responses":{"200":{"description":"The refunded debit"},"400":{"description":"Unknown debit, or one that is not confirmed"},"401":{"description":"Rail bearer key required"},"404":{"description":"KASH_RAIL_API_KEY unset"}}}},"/v1/kash/settlements/run":{"post":{"summary":"Settle a period NOW (operator key)","description":"Runs the SAME settleWeek the worker runs — identical pricing, caps and idempotency — against the period that is still accruing, instead of waiting for the settlement period to end. Points become real KSH immediately, which is what makes the product demonstrable. Safe to call repeatedly: settlement is keyed on (week, wallet), so points accrued after a run simply settle on the next one.","tags":["kash"],"security":[{"kash_adminKey":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"weekKey":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$","description":"Full ISO timestamp of the settlement period's start. Omit for the live period.","example":"2026-08-01T00:00:00.000Z"}}}}}},"responses":{"201":{"description":"Settlement report — wallets, KSH minted, mint tx"},"400":{"$ref":"#/components/responses/kash_BadRequest"},"401":{"description":"Missing or wrong operator bearer key"},"404":{"description":"KASH_TEST_ADMIN_KEY is not configured on this environment"}}}},"/v1/kash/admin/wallets/{wallet}/reset-subscription":{"post":{"summary":"[TEST ONLY] Return a wallet to the free tier","description":"The subscription desk refuses downgrades while a higher tier is live, so without this a tier ladder can only be walked upward, once. Returns 404 unless KASH_TEST_ADMIN_KEY is set. REMOVED BEFORE PRODUCTION.","tags":["kash"],"security":[{"kash_adminKey":[]}],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"example":"0x1111111111111111111111111111111111111111"}],"responses":{"201":{"description":"Subscription cleared; the wallet is back on tier 1"},"401":{"description":"Missing or wrong admin bearer key"},"404":{"description":"KASH_TEST_ADMIN_KEY is not configured on this environment"}}}},"/v1/kash/admin/wallets/{wallet}":{"delete":{"summary":"[TEST ONLY] Wipe a wallet back to a true zero","description":"Deletes points, settlements, balance, purchases, conversions, ledger, processed event ids and subscription, AND rewinds the wallet contribution to the global supply and treasury counters — so a re-run starts from zero rather than a state that merely looks empty. Returns 404 unless KASH_TEST_ADMIN_KEY is set. REMOVED BEFORE PRODUCTION.","tags":["kash"],"security":[{"kash_adminKey":[]}],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"example":"0x1111111111111111111111111111111111111111"}],"responses":{"200":{"description":"Row counts deleted per table"},"401":{"description":"Missing or wrong admin bearer key"},"404":{"description":"KASH_TEST_ADMIN_KEY is not configured on this environment"}}}},"/v1/kash/status":{"get":{"summary":"Full engine status: price, treasury, supply, tiers, epoch budgets","description":"The single source for every live parameter — render from this, never hardcode.","tags":["kash"],"responses":{"200":{"description":"Engine status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_StatusResponse"}}}}}}},"/v1/kash/treasury":{"get":{"summary":"Alias of /status (kept for compatibility)","tags":["kash"],"responses":{"200":{"description":"Engine status"}}}},"/v1/kash/treasury/coverage":{"get":{"summary":"Treasury solvency: USDC held vs. redeemable liability","description":"Worst case where every circulating KSH is redeemed at the current redemption price. Below 100% the desk is fractionally reserved — the number ops must watch.","tags":["kash"],"responses":{"200":{"description":"Coverage report"}}}},"/v1/kash/usernames/{username}/available":{"get":{"summary":"Whether a username is valid and free","description":"Usernames are 3–20 characters, lower-case letters, digits and underscores, starting with a letter; some names are reserved. The username is the wallet’s referral code.","tags":["kash"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"},"example":"ada_lovelace"}],"responses":{"200":{"description":"Availability verdict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_UsernameAvailabilityResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/profiles/{wallet}":{"get":{"summary":"A wallet's public profile: its username, if set","tags":["kash"],"parameters":[{"name":"wallet","in":"path","required":true,"schema":{"type":"string"},"example":"0x1111111111111111111111111111111111111111"}],"responses":{"200":{"description":"Profile (username null when none is set)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ProfileResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"}}}},"/v1/kash/profiles/me/username":{"put":{"summary":"Set the caller's username (once); it becomes their referral code","description":"The wallet comes from the verified Privy identity token, never from the body. 409 when the wallet already has a username or the name is taken; 502 (SERVICE_UNAVAILABLE) when identity verification is not configured.","tags":["kash"],"security":[{"kash_privyIdentity":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username"],"properties":{"username":{"type":"string","example":"ada_lovelace"}}}}}},"responses":{"200":{"description":"The profile as stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ProfileResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"},"401":{"$ref":"#/components/responses/kash_Unauthorized"},"409":{"$ref":"#/components/responses/kash_Conflict"}}}},"/v1/kash/referrals/claim":{"post":{"summary":"Record that the caller arrived through a referral code","description":"First claim wins and is permanent; a wallet cannot refer itself. The referral COUNTS for the referrer only once the caller has deposited (any rail), which the worker verifies on chain.","tags":["kash"],"security":[{"kash_privyIdentity":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","description":"The referrer’s username","example":"ada_lovelace"}}}}}},"responses":{"200":{"description":"The attribution as recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ReferralClaimResponse"}}}},"400":{"$ref":"#/components/responses/kash_BadRequest"},"401":{"$ref":"#/components/responses/kash_Unauthorized"},"404":{"description":"Unknown referral code"},"409":{"$ref":"#/components/responses/kash_Conflict"}}}},"/v1/kash/referrals/me":{"get":{"summary":"The caller's referral standing: username, referred (deposited) count, pending","tags":["kash"],"security":[{"kash_privyIdentity":[]}],"responses":{"200":{"description":"Referral stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ReferralStatsResponse"}}}},"401":{"$ref":"#/components/responses/kash_Unauthorized"}}}},"/v1/ramping/health":{"get":{"summary":"Service health","tags":["ramping"],"responses":{"200":{"description":"Health envelope"}}}},"/v1/ramping/onramps":{"post":{"summary":"Create an onramp order (NGN in → crypto out)","tags":["ramping"],"parameters":[{"name":"x-idempotency-key","in":"header","required":true,"description":"Stable, caller-generated key, reused verbatim on retries (8-200 chars). Retrying with the same key replays the original order instead of creating a second one.","schema":{"type":"string","minLength":8,"maxLength":200},"example":"onramp-user42-0001"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["destinationAddress"],"properties":{"destinationAddress":{"type":"string"},"destinationChainId":{"type":"integer","default":8453},"destinationAsset":{"type":"string","description":"Defaults to USDC on Base."},"expectedAmountNgn":{"type":"string","description":"Advisory only — any amount converts. Decimal STRING — monetary values are never numbers.","example":"3000.00"},"rate":{"type":"string","description":"Per-order rate override, NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1650.00"},"reference":{"type":"string","maxLength":100}}},"example":{"destinationAddress":"0xD59a229641DD869e34888013D1C4c1868f62af59","expectedAmountNgn":"3000.00","reference":"order-4821"}}}},"responses":{"201":{"description":"The order with its payment account","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","example":"cmszrx3pr0002k6dvn4584iia"},"integrator_ref":{"type":"string","nullable":true},"rate":{"type":"string","description":"Locked NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1650.00"},"expected_ngn":{"type":"string","description":"Advisory expected NGN. Decimal STRING — monetary values are never numbers.","example":"3000.00","nullable":true},"payment_account":{"type":"object","nullable":true,"properties":{"account_number":{"type":"string","example":"8881723738"},"account_name":{"type":"string","example":"Onramp c1dz5i29"},"bank_name":{"type":"string","example":"Rubies MFB"}}},"destination_address":{"type":"string","example":"0xD59a229641DD869e34888013D1C4c1868f62af59"},"destination_chain_id":{"type":"integer","example":8453},"destination_asset":{"type":"string","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"amount_ngn":{"type":"string","description":"NGN received. Decimal STRING — monetary values are never numbers.","example":"3000.00","nullable":true},"amount_usdc":{"type":"string","description":"USDC delivered (6 dp). Decimal STRING — monetary values are never numbers.","example":"1.818181","nullable":true},"status":{"type":"string","enum":["awaiting_payment","paid","delivering","completed","failed","expired"],"description":"expired means the LOCKED RATE lapsed — the payment account stays live forever; later payments requote at the current rate."},"error":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}},"502":{"description":"Rail failure (mapped)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}}}},"get":{"summary":"List onramp orders","tags":["ramping"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"A page of orders","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cmszrx3pr0002k6dvn4584iia"},"integrator_ref":{"type":"string","nullable":true},"rate":{"type":"string","description":"Locked NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1650.00"},"expected_ngn":{"type":"string","description":"Advisory expected NGN. Decimal STRING — monetary values are never numbers.","example":"3000.00","nullable":true},"payment_account":{"type":"object","nullable":true,"properties":{"account_number":{"type":"string","example":"8881723738"},"account_name":{"type":"string","example":"Onramp c1dz5i29"},"bank_name":{"type":"string","example":"Rubies MFB"}}},"destination_address":{"type":"string","example":"0xD59a229641DD869e34888013D1C4c1868f62af59"},"destination_chain_id":{"type":"integer","example":8453},"destination_asset":{"type":"string","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"amount_ngn":{"type":"string","description":"NGN received. Decimal STRING — monetary values are never numbers.","example":"3000.00","nullable":true},"amount_usdc":{"type":"string","description":"USDC delivered (6 dp). Decimal STRING — monetary values are never numbers.","example":"1.818181","nullable":true},"status":{"type":"string","enum":["awaiting_payment","paid","delivering","completed","failed","expired"],"description":"expired means the LOCKED RATE lapsed — the payment account stays live forever; later payments requote at the current rate."},"error":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"total_pages":{"type":"integer"},"has_more":{"type":"boolean"}}}}}}}}}}}}},"/v1/ramping/onramps/{id}":{"get":{"summary":"Get one onramp order","tags":["ramping"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The order","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","example":"cmszrx3pr0002k6dvn4584iia"},"integrator_ref":{"type":"string","nullable":true},"rate":{"type":"string","description":"Locked NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1650.00"},"expected_ngn":{"type":"string","description":"Advisory expected NGN. Decimal STRING — monetary values are never numbers.","example":"3000.00","nullable":true},"payment_account":{"type":"object","nullable":true,"properties":{"account_number":{"type":"string","example":"8881723738"},"account_name":{"type":"string","example":"Onramp c1dz5i29"},"bank_name":{"type":"string","example":"Rubies MFB"}}},"destination_address":{"type":"string","example":"0xD59a229641DD869e34888013D1C4c1868f62af59"},"destination_chain_id":{"type":"integer","example":8453},"destination_asset":{"type":"string","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"amount_ngn":{"type":"string","description":"NGN received. Decimal STRING — monetary values are never numbers.","example":"3000.00","nullable":true},"amount_usdc":{"type":"string","description":"USDC delivered (6 dp). Decimal STRING — monetary values are never numbers.","example":"1.818181","nullable":true},"status":{"type":"string","enum":["awaiting_payment","paid","delivering","completed","failed","expired"],"description":"expired means the LOCKED RATE lapsed — the payment account stays live forever; later payments requote at the current rate."},"error":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}}}}}}},"/v1/ramping/offramps":{"post":{"summary":"Create an offramp order (crypto in → NGN to a bank)","tags":["ramping"],"parameters":[{"name":"x-idempotency-key","in":"header","required":true,"description":"Stable, caller-generated key, reused verbatim on retries (8-200 chars). Retrying with the same key replays the original order instead of creating a second one.","schema":{"type":"string","minLength":8,"maxLength":200},"example":"onramp-user42-0001"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["originChainId","originAsset","destinationAccount","destinationBankUuid"],"properties":{"originChainId":{"type":"integer","example":8453},"originAsset":{"type":"string"},"destinationAccount":{"type":"string","pattern":"^\\d{10}$"},"destinationBankUuid":{"type":"string"},"expectedAmount":{"type":"string","description":"Advisory expected origin amount. Decimal STRING — monetary values are never numbers.","example":"2"},"rate":{"type":"string","description":"Per-order rate override. Decimal STRING — monetary values are never numbers.","example":"1600.00"},"reference":{"type":"string","maxLength":100}}}}}},"responses":{"201":{"description":"The order with its deposit address","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string"},"integrator_ref":{"type":"string","nullable":true},"rate":{"type":"string","description":"Locked NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1600.00"},"origin_chain_id":{"type":"integer","example":8453},"origin_asset":{"type":"string","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"deposit_address":{"type":"string","nullable":true,"description":"Permanent per-order crypto deposit address on the origin chain."},"destination_account":{"type":"string","example":"8146942299"},"destination_bank_uuid":{"type":"string"},"recipient_name":{"type":"string","nullable":true},"amount_usdc":{"type":"string","description":"USDC settled. Decimal STRING — monetary values are never numbers.","example":"1.971271","nullable":true},"amount_ngn":{"type":"string","description":"NGN paid out. Decimal STRING — monetary values are never numbers.","example":"3154.03","nullable":true},"status":{"type":"string","enum":["awaiting_deposit","funded","paying_out","completed","failed","expired"]},"error":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}},"502":{"description":"Rail failure (mapped)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}}}},"get":{"summary":"List offramp orders","tags":["ramping"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"A page of orders","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"integrator_ref":{"type":"string","nullable":true},"rate":{"type":"string","description":"Locked NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1600.00"},"origin_chain_id":{"type":"integer","example":8453},"origin_asset":{"type":"string","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"deposit_address":{"type":"string","nullable":true,"description":"Permanent per-order crypto deposit address on the origin chain."},"destination_account":{"type":"string","example":"8146942299"},"destination_bank_uuid":{"type":"string"},"recipient_name":{"type":"string","nullable":true},"amount_usdc":{"type":"string","description":"USDC settled. Decimal STRING — monetary values are never numbers.","example":"1.971271","nullable":true},"amount_ngn":{"type":"string","description":"NGN paid out. Decimal STRING — monetary values are never numbers.","example":"3154.03","nullable":true},"status":{"type":"string","enum":["awaiting_deposit","funded","paying_out","completed","failed","expired"]},"error":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"total_pages":{"type":"integer"},"has_more":{"type":"boolean"}}}}}}}}}}}}},"/v1/ramping/offramps/{id}":{"get":{"summary":"Get one offramp order","tags":["ramping"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The order","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string"},"integrator_ref":{"type":"string","nullable":true},"rate":{"type":"string","description":"Locked NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1600.00"},"origin_chain_id":{"type":"integer","example":8453},"origin_asset":{"type":"string","example":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},"deposit_address":{"type":"string","nullable":true,"description":"Permanent per-order crypto deposit address on the origin chain."},"destination_account":{"type":"string","example":"8146942299"},"destination_bank_uuid":{"type":"string"},"recipient_name":{"type":"string","nullable":true},"amount_usdc":{"type":"string","description":"USDC settled. Decimal STRING — monetary values are never numbers.","example":"1.971271","nullable":true},"amount_ngn":{"type":"string","description":"NGN paid out. Decimal STRING — monetary values are never numbers.","example":"3154.03","nullable":true},"status":{"type":"string","enum":["awaiting_deposit","funded","paying_out","completed","failed","expired"]},"error":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}}}}}}},"/v1/ramping/rates":{"get":{"summary":"Current default conversion rates (NGN per USDC)","tags":["ramping"],"responses":{"200":{"description":"Rates","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"onramp_rate":{"type":"string","nullable":true,"example":"1650.00"},"offramp_rate":{"type":"string","nullable":true,"example":"1600.00"},"updated_at":{"type":"string","nullable":true}}}}}}}}}},"patch":{"summary":"Set default rates","tags":["ramping"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"onrampRate":{"type":"string","description":"NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1650.00"},"offrampRate":{"type":"string","description":"NGN per USDC. Decimal STRING — monetary values are never numbers.","example":"1600.00"}}},"example":{"onrampRate":"1650.00","offrampRate":"1600.00"}}}},"responses":{"200":{"description":"Updated rates"},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}},"502":{"description":"Rail failure (mapped)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}}}}},"/v1/ramping/balances":{"get":{"summary":"Both rails in one call","tags":["ramping"],"responses":{"200":{"description":"USDC (chain-true) + NGN balances","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"usdc":{"type":"object","properties":{"balance":{"type":"string","description":"USDC (6 dp), read live from Base. Decimal STRING — monetary values are never numbers.","example":"2.642956"},"address":{"type":"string"}}},"ngn":{"type":"object","properties":{"balance":{"type":"string","description":"NGN (2 dp). Decimal STRING — monetary values are never numbers.","example":"7444.53"},"deposit_account":{"type":"object","nullable":true,"properties":{"account_number":{"type":"string","example":"8881723738"},"account_name":{"type":"string","example":"Onramp c1dz5i29"},"bank_name":{"type":"string","example":"Rubies MFB"}}}}}}}}}}}}}}},"/v1/ramping/banks":{"get":{"summary":"Supported Nigerian banks","tags":["ramping"],"parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Case-insensitive name filter."}],"responses":{"200":{"description":"Banks","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string"},"name":{"type":"string"}}}}}}}}}}}},"/v1/ramping/banks/resolve":{"post":{"summary":"Resolve an account number to the holder's name","tags":["ramping"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountNumber","bankUuid"],"properties":{"accountNumber":{"type":"string","pattern":"^\\d{10}$"},"bankUuid":{"type":"string"}}}}}},"responses":{"200":{"description":"The account holder","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"account_name":{"type":"string"}}}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}},"502":{"description":"Rail failure (mapped)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}}}}},"/v1/ramping/webhooks/difference":{"post":{"summary":"Difference rail webhook receiver (rail-facing, not for clients)","tags":["ramping"],"description":"Verifies HMAC-SHA256 over \"<timestamp>.<raw body>\" (X-Difference-Signature / X-Difference-Timestamp, 300s tolerance), mirrors order state, and republishes platform events (ramping.* on the broker). Idempotent on the event id.","responses":{"200":{"description":"Delivery accepted"},"401":{"description":"Signature verification failed"},"503":{"description":"Webhook secret not configured yet"}}}},"/v1/prediction-market/markets":{"get":{"summary":"List markets","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["Open","Closed","Resolved","Invalid"]}}],"responses":{"200":{"description":"Markets with live prices/reserves/volume"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/mine":{"get":{"summary":"A creator's own markets (to resolve them)","description":"Lists the markets created by the given wallet, matched on the on-chain creator.","parameters":[{"name":"wallet","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The wallet's created markets"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}":{"get":{"summary":"Market detail","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Market"},"404":{"description":"Not found"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/prices":{"get":{"summary":"YES price history (for charts)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Price points (priceYes in 1e6)"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/trades":{"get":{"summary":"Recent trades for a market","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Trade feed"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/chart":{"get":{"summary":"Time-bucketed YES/NO price series for a chart","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"interval","in":"query","schema":{"type":"string","enum":["1m","5m","15m","1h","4h","1d"],"default":"1h"}}],"responses":{"200":{"description":"[{ t, yes, no }] — prices in 1e6"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/metadata":{"post":{"summary":"Attach off-chain metadata (question, category) to a market","description":"Keyless — records metadata for an on-chain market, signs nothing. Called after the market is created on-chain from the user wallet. Honors an optional Idempotency-Key header (a retry replays the first response).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Stable client key; a retry replays the first response. 409 on reuse with a different body.","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string"},"category":{"type":"string"},"imageUrl":{"type":"string"}}}}}},"responses":{"200":{"description":"Metadata attached"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/image":{"post":{"summary":"Upload a market image (hosted on Cloudinary)","description":"Uploads a base64 image data URL, hosts it, and attaches the resulting URL to the market metadata. Returns the hosted imageUrl. 503 when image hosting is not configured. Honors an optional Idempotency-Key header so a retry does not re-upload.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Stable client key; a retry replays the first response instead of re-uploading. 409 on reuse with a different body.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["image"],"properties":{"image":{"type":"string","description":"Base64 image data URL, e.g. \"data:image/png;base64,…\" (≤ 5 MiB)."}}}}}},"responses":{"200":{"description":"Hosted image URL"}},"tags":["prediction-market"]}},"/v1/prediction-market/categories":{"get":{"summary":"Distinct market categories","responses":{"200":{"description":"string[]"}},"tags":["prediction-market"]}},"/v1/prediction-market/positions":{"get":{"summary":"A wallet's positions across markets","parameters":[{"name":"wallet","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Positions (YES/NO shares, cost)"}},"tags":["prediction-market"]}},"/v1/prediction-market/positions/{id}":{"get":{"summary":"A wallet's position in one market","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"wallet","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Position"}},"tags":["prediction-market"]}},"/v1/prediction-market/lp":{"get":{"summary":"A wallet's LP positions","parameters":[{"name":"wallet","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"LP positions"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/holders":{"get":{"summary":"Top holders of a market side (Yes/No leaderboard)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"side","in":"query","schema":{"type":"string","enum":["yes","no"],"default":"yes"}},{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Largest positions first"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/activity":{"get":{"summary":"Activity feed (trades, LP, redeems, resolution), newest first","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"\"<block>:<log>\" from the previous page"},{"name":"limit","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"{ items, nextCursor }"}},"tags":["prediction-market"]}},"/v1/prediction-market/markets/{id}/quote":{"get":{"summary":"Size-aware CPMM quote (preview a trade before signing)","description":"Computes shares/avg-price/impact with the same math the contract uses. amount is USDC (buy) or shares (sell) in 1e6 base units.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"side","in":"query","schema":{"type":"string","enum":["yes","no"],"default":"yes"}},{"name":"kind","in":"query","schema":{"type":"string","enum":["buy","sell"],"default":"buy"}},{"name":"amount","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Quote"},"404":{"description":"Not found"}},"tags":["prediction-market"]}},"/v1/prediction-market/groups":{"get":{"summary":"List multi-outcome EVENTS (candidate-style grouped markets)","parameters":[{"name":"category","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["Open","Closed","Resolved"]}}],"responses":{"200":{"description":"Events with aggregated outcomes"}},"tags":["prediction-market"]},"post":{"summary":"Create a multi-outcome event (off-chain metadata)","description":"Keyless — records event metadata; each outcome is a real on-chain binary market attached as a member.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["slug","title"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"description":{"type":"string"},"rules":{"type":"string"},"resolutionSource":{"type":"string"},"imageUrl":{"type":"string"},"closeTime":{"type":"integer"}}}}}},"responses":{"201":{"description":"Created event"}},"tags":["prediction-market"]}},"/v1/prediction-market/groups/{id}":{"get":{"summary":"Event detail with per-outcome prices, volumes, normalized %","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"id or slug"}],"responses":{"200":{"description":"Event"},"404":{"description":"Not found"}},"tags":["prediction-market"]}},"/v1/prediction-market/groups/{id}/members":{"post":{"summary":"Attach an on-chain market to an event as a labelled outcome","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["marketId","label"],"properties":{"marketId":{"type":"string"},"label":{"type":"string"},"imageUrl":{"type":"string"},"sortOrder":{"type":"integer"}}}}}},"responses":{"201":{"description":"Member attached"}},"tags":["prediction-market"]}},"/v1/prediction-market/comments":{"get":{"summary":"List comments for an event or a market","parameters":[{"name":"groupId","in":"query","schema":{"type":"string"}},{"name":"marketId","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"Comments, newest first"}},"tags":["prediction-market"]},"post":{"summary":"Post a comment (wallet-signature verified)","description":"The client signs a deterministic message (scope+body+timestamp) with the embedded wallet; the API recovers the signer and rejects if it does not match `wallet`. No server key, non-custodial.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scope","scopeId","body","wallet","signature","timestamp"],"properties":{"scope":{"type":"string","enum":["group","market"]},"scopeId":{"type":"string"},"body":{"type":"string"},"wallet":{"type":"string"},"signature":{"type":"string"},"timestamp":{"type":"integer"},"parentId":{"type":"string"}}}}}},"responses":{"201":{"description":"Comment id"},"403":{"description":"Bad signature"}},"tags":["prediction-market"]}},"/v1/prediction-market/comments/{id}/like":{"post":{"summary":"Like a comment (signature-verified)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ commentId, likeCount }"}},"tags":["prediction-market"]}},"/v1/prediction-market/health":{"get":{"summary":"Health probe","responses":{"200":{"description":"OK"}},"tags":["prediction-market"]}},"/v1/market-square/health":{"get":{"summary":"Service health","tags":["market-square"],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_HealthStatus"}}}}}}}}},"/v1/market-square/openapi.json":{"get":{"summary":"This API contract","tags":["market-square"],"responses":{"200":{"description":"OpenAPI 3.0 document"}}}},"/v1/market-square/profiles":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Public people directory — Explore's People tab","description":"Lists profiles, most-followed first, with optional free-text search. This is the browse surface: unlike GET /search?type=people (which returns an EMPTY set for a blank query, by design) a blank `q` here lists everyone. Authentication is OPTIONAL: it resolves `isFollowing` (OMITTED entirely for anonymous readers — never a misleading `false`) and it excludes the caller.\n\nWHAT THIS OMITS, deliberately — all three decided rather than inherited:\n\n1. **The authenticated caller.** This is a discovery surface; your own row cannot offer a Follow button, so it reads as broken. NOTE THE PAGINATION CONSEQUENCE: an anonymous request and the same request signed in return DIFFERENT totals — signed in is one fewer. This is done in the query, not the client, so a page of 30 stays a page of 30. It applies ONLY here: follower/following lists and GET /search?type=people still include you, because those are factual lists and hiding yourself there would suppress true information.\n2. **Profiles with no username.** A profile row is auto-created on a user's first authenticated call, so the table holds shells with no username, display name or avatar; a directory of blank cards is worse than a shorter directory.\n3. **Nothing else.** The ARK/house and MARKET accounts, unverified citizens and zero-follower profiles all appear — a house account is a real account people want to find, and hiding low-follower profiles would make the directory a leaderboard. Profiles carry no ban or soft-delete flag in this service today; when one lands it belongs in this list.\n\nModeration facets (role, verification, orgBadge, isAdmin) are admin-only on GET /admin/profiles: `?verification=pending` would publish who has applied for a badge. Both routes run the SAME underlying query, so they cannot drift.","tags":["market-square"],"parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":200},"description":"Free-text over username and display name. Wildcards are escaped. Blank/absent lists everyone."},{"name":"sort","in":"query","schema":{"type":"string","enum":["followers","recent"],"default":"followers"},"description":"Server-side ordering: `followers` = most-followed first (default), `recent` = most recently active first. Sorting is NEVER left to the client — re-sorting one loaded page makes page 1 look ordered while page 2 contradicts it. The cursor encodes the sort key, so paging is stable across both orders."},{"name":"city","in":"query","schema":{"type":"string","maxLength":80},"description":"Self-declared place facet. Matched case-insensitively and EXACTLY: `lagos` and `Lagos` are one place, `Lag` matches nothing. Server-side for the same reason the sort is — a client filtering one loaded page turns a page of 30 into however many happened to match, and a cursor cannot top that up. Facets COMPOSE with each other and with `q`. Somebody who has not declared one is never returned by a facet, since null is not a value."},{"name":"region","in":"query","schema":{"type":"string","maxLength":80},"description":"Self-declared place facet. See city. Only finds people whose location precision shows their region; `city` likewise only finds people who show their city."},{"name":"country","in":"query","schema":{"type":"string","minLength":2,"maxLength":2},"description":"Two-letter country code, any case. Only finds people who show their country (not continent-only). A code not in the list is a 400."},{"name":"gender","in":"query","schema":{"type":"string","enum":["male","female"]},"description":"Self-declared facet: `male` or `female`, matched case-insensitively (`Female` works). Any other value is a 400 rather than an empty page, so a typo cannot pass for \"nobody matched\". A blank value is no facet. Composes with q, city, region and excludeFollowing."},{"name":"excludeFollowing","in":"query","schema":{"type":"string","enum":["true","false"]},"description":"Drop people the CALLER already follows — what makes a \"people to follow\" surface mean anything, since suggesting somebody you already follow reads as broken. Server-side because it cannot be done anywhere else: removing rows from a loaded page costs a row no cursor can top back up, so a long list silently runs short. It COMPOSES with the place facets, so `?city=Lagos&excludeFollowing=true` is \"people in Lagos I do not follow yet\". ONE DIRECTION only — somebody who follows YOU is still suggested, because you have not followed them. A no-op for a signed-out reader, and correctly so: they follow nobody, so nobody is excluded. The CALLER is always excluded from this route regardless, authenticated or not — no client-side self-filtering is needed."},{"name":"withMutualFollowers","in":"query","schema":{"type":"string","enum":["true","false"]},"description":"Resolve `mutualFollowers` on each row — people the CALLER follows who also follow that person. OFF BY DEFAULT and opt-in, because it is not free: two extra queries per page, one of them proportional to how many people the caller follows. A surface that does not draw the line must not pay for it. A no-op for a signed-out reader, who has no following list to intersect."},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Page of public profiles","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_PublicProfile"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/profiles/{username}":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Public profile by username (isFollowing included when authed)","tags":["market-square"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"},"description":"Username, or the profile id (Privy DID, e.g. did:privy:...) for profiles with an unclaimed username. Colons may be URL-encoded."}],"responses":{"200":{"description":"The profile","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_PublicProfile"}}}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me":{"get":{"summary":"Own profile (includes walletAddress)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"Own profile","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Profile"}}}}}},"401":{"description":"Missing/invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"patch":{"summary":"Update own profile","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_UpdateMeRequest"}}}},"responses":{"200":{"description":"Updated profile","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Profile"}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — username taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{id}/follow":{"post":{"summary":"Follow a profile (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Follow state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_FollowResult"}}}}}},"400":{"description":"Cannot follow yourself","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Unfollow a profile (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Follow state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_FollowResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{id}/block":{"post":{"summary":"Block a profile (idempotent)","description":"A viewer's own decision about a person: global, owned by them, and unrelated to a stream ban (which is a host silencing somebody in ONE room). Blocking SEVERS THE FOLLOW IN BOTH DIRECTIONS — you do not keep a subscription to somebody you blocked, and leaving theirs in place would keep publishing your posts to them. It also suppresses delivery of anything either of you addresses to the other (today: winks).\n\nDeliberately NOT rate limited. Every other write here has a budget because spending it costs somebody else something; blocking costs only the person doing it, and a safety control that can be exhausted fails exactly when somebody is being harassed hardest.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Block state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_BlockResult"}}}}}},"400":{"description":"Cannot block yourself","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Unblock a profile (idempotent)","description":"Does NOT restore the follow the block severed. The block did not borrow it, and re-subscribing somebody to an account they had cut off would be a surprise in the one place surprises are least welcome.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Block state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_BlockResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{id}/views":{"post":{"summary":"Record that the caller viewed a profile — send on DWELL, not on page load","description":"Adds the caller to the profile owner’s \"who viewed my profile\" list. Send it when somebody actually stays on a profile, never as a side effect of loading one: GET /profiles/{username}, a hover card or a prefetch records nothing.\n\n**Once a day** — one line per person. A repeat view on the same UTC day changes nothing; a later day moves the time.\n\n**Not recorded, and answered identically (204)**: a view of your own profile, a view while the caller has `privateBrowsing` on, and a view between two people where EITHER has blocked the other. A different answer for a block would tell somebody they had been blocked.\n\n`id` is the profile id (the Privy DID), as for follow and block.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Accepted. Identical whether or not it was recorded."},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{id}/wink":{"post":{"summary":"Wink at a profile — a one-tap signal of interest","description":"Addressed to a PERSON, unlike a like (addressed to a post) and unlike a follow (a public subscription). It costs the sender nothing and arrives at somebody who did not ask for it, which is why it carries two independent limits.\n\n**RATE** — an hourly budget (`WINK_RATE_LIMIT_PER_HOUR`, default 12) and a PER-PERSON COOLDOWN (`WINK_COOLDOWN_HOURS`, default 24). Both return 429 with the usual `error.details = { action, limit, windowSeconds, retryAfterSeconds }`, but they are different refusals and the message says which: the budget is the spam ceiling, the cooldown is the harassment one. A budget alone still permits twelve winks at ONE person inside a minute. The cooldown is answered from the `winks` table rather than Redis, because it is a promise to the recipient and must survive a cache flush; its `retryAfterSeconds` is therefore exact rather than the whole window.\n\n**BLOCKS** — a wink between two people where EITHER has blocked the other is accepted, charged, recorded, and NEVER DELIVERED, and the response is byte-identical to a delivered one. This is not sloppiness: a distinguishable response is a block-detector — send a wink, read the error, learn you have been blocked — which is exactly the fact blocking exists to withhold, and learning it is what makes somebody open a second account. It is still CHARGED, because a refusal that costs nothing is a free retry and a blocked account would get an unlimited supply of them. The one asymmetry: the caller's OWN block is reported plainly (400), because they set it.\n\nDelivered winks create a `wink` notification on `GET /me/notifications`.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Wink sent (delivery is never reported)","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_WinkResult"}}}}}},"400":{"description":"Cannot wink yourself, or you have blocked them","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{id}/followers":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Followers page","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Follower page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ProfileSummary"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/profiles/{id}/following":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Following page","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Following page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ProfileSummary"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/profiles/{username}/posts":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"A profile's active posts (public profile page)","tags":["market-square"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"},"description":"Username, or the profile id (Privy DID) for unclaimed usernames."},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Post page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_FeedItem"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{username}/streams":{"get":{"summary":"A profile's streams (public profile page)","tags":["market-square"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"},"description":"Username, or the profile id (Privy DID) for unclaimed usernames."},{"name":"status","in":"query","schema":{"type":"string","enum":["live","scheduled","ended"]},"description":"Same vocabulary as GET /streams, deliberately — two spellings of one concept is how a client sends `finished` to one route and `ended` to another."},{"name":"kind","in":"query","schema":{"type":"string","enum":["broadcast","room"]},"description":"Narrow to broadcasts or gist rooms. Applied in the QUERY, not by the caller: a Replays rail wanting this person’s ENDED ROOMS would otherwise page through every broadcast they have ever made, and a client-filtered page under cursor pagination runs short with nothing to top it up."},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Stream page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Stream"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{username}/houses":{"get":{"summary":"The houses a profile belongs to (their profile's House rail)","description":"PUBLIC houses always. A PRIVATE house appears ONLY when the CALLER is in it too — membership of a private group is itself private, and listing one would tell a stranger both that the group exists and who is in it. The rule is applied in the query rather than by filtering afterwards, so a forgotten call site cannot leak a house. Ordered biggest-first, the same order and cursor shape as GET /conversations/discover, so a client pages both by one rule.","tags":["market-square"],"security":[{},{"market-square_bearerAuth":[]}],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"},"description":"Username, or the profile id (Privy DID) for unclaimed usernames."},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"House page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ConversationSummary"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{username}/activities":{"get":{"summary":"A profile's activities (public profile page)","tags":["market-square"],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"},"description":"Username, or the profile id (Privy DID) for unclaimed usernames."},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Activity page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Activity"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/stories":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Active 24h stories (the rail)","description":"scope=all (DEFAULT) returns every active story, ordered in BANDS when authenticated: the viewer own stories, then authors they follow, then everyone else — each band newest-first. A user who follows nobody therefore still sees a populated rail. scope=following returns the strict set (viewer + followed authors). Because `all` is ranked globally, its cursor is a RANK OFFSET, not a post id; `following` pages by id. Stories never appear in the timeline lanes.","tags":["market-square"],"parameters":[{"name":"scope","in":"query","schema":{"type":"string","enum":["all","following"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Story page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_FeedItem"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/posts":{"post":{"summary":"Create a post or 24h story (rate limit 10/min)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_CreatePostRequest"}}}},"responses":{"201":{"description":"The post","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Post"}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"One post (removed/expired stories → 404)","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The post","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"allOf":[{"$ref":"#/components/schemas/market-square_Post"},{"type":"object","properties":{"author":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Who wrote it, in the SAME shape /feed returns, so one card renders both. Carries `isFollowing` for the viewer, so a permalink can draw the Follow button in the right state; absent for a signed-out reader, as on the feed. NULL only when the profile row has gone — render that as a missing author, not as an error, because the post is still real."},"likedByMe":{"type":"boolean"},"bookmarkedByMe":{"type":"boolean"},"quotedPost":{"nullable":true,"description":"The post this one quotes, one level deep. `unavailable: true` when the original was removed or expired.","type":"object"}}}]}}}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"patch":{"summary":"Edit own post — text and topics (author only)","description":"Rewrites what the author wrote. TEXT and TOPICS only: media, quote and deep link are deliberately not editable, because swapping the picture under a post people have already liked, quoted and replied to changes what they endorsed — that is a delete-and-repost, not a typo fix. Every edit stamps `editedAt`, which is how a client draws its \"edited\" marker; there is no quiet window in which an edit goes unrecorded. Hashtags are re-indexed from the new text, so a tag the author removed stops appearing on that tag page and one they added starts. The author and ONLY the author: unlike delete there is no admin path, because an admin who could rewrite somebody’s words could put words in their mouth. Text obeys the same 2000 cap as create. Works on a story as well as an update.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","minLength":1,"maxLength":2000},"topics":{"type":"array","items":{"type":"string"},"maxItems":20}}}}}},"responses":{"200":{"description":"The edited post","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Post"}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the author","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Soft-remove own post (author only) — also how a story is deleted","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"removed":{"type":"boolean"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the author","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}/like":{"post":{"summary":"Like a post (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Like state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_LikeResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Unlike a post (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Like state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_LikeResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}/repost":{"post":{"summary":"Repost a post (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repost state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_RepostResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Undo a repost (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repost state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_RepostResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/hashtags/trending":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Trending discussions — the hashtags people are using now","description":"Ranked by DISTINCT AUTHORS, not post volume: one person posting the same tag forty times is not a trend, and ordering by raw count is how a spammer reaches the top of a discovery surface. The window is short (48h) because a discussion older than that has had its day. Tags are lowercase; `#Bitcoin` and `#bitcoin` are one discussion.","tags":["market-square"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Trending discussions, busiest first","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_TrendingDiscussion"}}}}}}}}}}}},"/v1/market-square/tips/capability":{"get":{"summary":"Whether tipping is available, and the amount band","description":"Public. Clients MUST consult this before drawing a tip control: `enabled` is false whenever the configured payment rail has no transfer primitive, and a button offered in that state can only ever fail.","tags":["market-square"],"responses":{"200":{"description":"Tip capability","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_TipCapability"}}}}}}}}},"/v1/market-square/posts/{id}/tips":{"post":{"summary":"Tip a post author in KASH","description":"Moves `amountKash` from the caller to the post author in ONE rail transfer, then writes both ledger legs. Refused before any money moves when: the rail cannot transfer (501), the caller is the author (403), the author is not verified and policy requires it (403), the amount is outside the configured band (400), or a tip from this caller on this post is still in flight (409).","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_SendTipRequest"}}}},"responses":{"201":{"description":"The settled tip","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Tip"}}}}}},"400":{"description":"VALIDATION_ERROR — amount malformed or outside the band","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"402":{"description":"PAYMENT_FAILED — the rail declined (e.g. insufficient balance)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — own post, or author cannot receive tips","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — a tip on this post is already in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"501":{"description":"NOT_IMPLEMENTED — this payment rail cannot transfer between users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}/tips/{tipId}/transfer":{"post":{"summary":"Report the transfer the sender signed for a post tip","description":"RECORDED, NOT BELIEVED. A reported hash is a claim: crediting on it would pay an author for a transfer that may never have happened, and settling on the hash alone would let a caller point a tip at any transfer on the chain. The tip stays `pending` and settles only when the watcher observes that transfer and the amount and both wallets match. A hash already recorded against another tip is refused.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"tipId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_TipTransferRequest"}}}},"responses":{"200":{"description":"The tip, still pending until the chain confirms it","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Tip"}}}}}},"400":{"description":"VALIDATION_ERROR — malformed transaction hash","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — not the sender of this tip","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Tip not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — that transfer is already recorded against a tip","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/tickets/{ticketId}/transfer":{"post":{"summary":"Report the transfer the buyer signed for a ticket","description":"RECORDED, NOT BELIEVED. The ticket stays `pending` and is granted only when the watcher observes that transfer paying the TREASURY the exact price from the buyer's own wallet. Confirming on the hash alone would let somebody point a ticket at any transfer on the chain and walk into a paid stream for nothing; a transfer paid anywhere else fails the ticket rather than settling it. `tx_hash` is unique, so one transfer can never admit two people.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"ticketId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_TipTransferRequest"}}}},"responses":{"200":{"description":"The ticket, still pending until the chain confirms it","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Ticket"}}}}}},"400":{"description":"VALIDATION_ERROR — malformed transaction hash","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — not the buyer of this ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Ticket not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — that transfer is already settling another ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/gifts":{"post":{"summary":"Gift the host of a live stream in KASH","description":"A gift is a tip addressed to a STREAM rather than a post: the same money movement, one viewer paying one creator, settled down the same path so the two cannot drift apart. DELIBERATELY not the payment rail — a rail debit BURNS the tokens (the KASH chain exposes mint and burn and no transfer), which would destroy the gift instead of paying the host. Refused before any money moves when the caller is the host (403), the host cannot receive (403), the amount is outside the band (400), or a gift from this caller on this stream is still in flight (409).","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_SendTipRequest"}}}},"responses":{"201":{"description":"The gift — settled, or pending the signed transfer","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Tip"}}}}}},"400":{"description":"VALIDATION_ERROR — amount malformed or outside the band","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"402":{"description":"PAYMENT_FAILED — the rail declined","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — your own stream, or the host cannot receive gifts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — a gift on this stream is already in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"501":{"description":"NOT_IMPLEMENTED — this payment rail cannot transfer between users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/gifts/{tipId}/transfer":{"post":{"summary":"Report the transfer the sender signed for a live gift","description":"Identical in every respect to the post-tip transfer endpoint — one settlement path serves both targets. The hash is recorded, never believed; the gift settles only when the watcher sees that transfer with a matching amount and both wallets.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"tipId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_TipTransferRequest"}}}},"responses":{"200":{"description":"The gift, still pending until the chain confirms it","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Tip"}}}}}},"400":{"description":"VALIDATION_ERROR — malformed transaction hash","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — not the sender of this gift","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Gift not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — that transfer is already recorded against a tip","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/tips/received":{"get":{"summary":"The caller's confirmed tips received (earnings)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Received tips, newest first","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_TipWithContext"}}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/pulse":{"post":{"summary":"Cast or change this viewer's Market Pulse vote","description":"One standing vote per viewer. Changing your mind moves your vote rather than adding a second. Refused once a stream has ended: voting on how a finished room feels is voting on the past.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["choice"],"properties":{"choice":{"type":"string","enum":["bullish","neutral","bearish"]}}}}}},"responses":{"200":{"description":"Resulting tallies and your choice","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_PulseResult"}}}}}},"400":{"description":"Stream has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/pulse/me":{"get":{"summary":"This viewer's own pulse choice, or null","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Your choice","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_MyPulse"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/reactions":{"post":{"summary":"Record a burst of hearts on a live stream","description":"REPEATABLE, unlike a post like: a heart is applause, so the same viewer adds to the tally every time they tap. Nothing is stored per tap — only the stream's running total moves, and the floating hearts themselves still travel over the room's data channel. Clients coalesce rapid tapping and send how many accumulated, capped at 10 per request, so holding the button costs one write a second rather than one per heart. Refused once a stream has ended: the tally on a finished broadcast is a record of how that room felt while it was happening.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"burst":{"type":"integer","minimum":1,"maximum":10,"default":1}}}}}},"responses":{"200":{"description":"The resulting tally","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StreamReactionResult"}}}}}},"400":{"description":"Stream has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}/views":{"post":{"summary":"Record that the caller has seen a post (once per viewer)","description":"Counted once per (post, viewer): a re-watch returns the unchanged tally. Viewing your own post is not counted. Signed-out views are not counted at all, because there is no trustworthy identity to deduplicate them by.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"View tally","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ViewResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}/bookmark":{"post":{"summary":"Bookmark a post (\"Arkmark\", idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Bookmark state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_BookmarkResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Remove a bookmark (idempotent)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Bookmark state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_BookmarkResult"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/settings":{"get":{"summary":"The caller’s settings: notification toggles and who may message them","description":"Somebody who never saved reads as the defaults: `notifications { friendsRooms: true, direct: true }`, `chat { messagesFrom: \"everyone\", allowHouseMembers: true, allowPastAudience: false }`. Privacy settings join this object when the features they govern exist.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"The settings","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfileSettings"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"patch":{"summary":"Change settings — partial and nested, answers the whole object","description":"Only the keys sent change. STRICT at every level: an unknown key, a value outside the choices, or an empty body is a 400.\n\n**notifications.friendsRooms** — a person you follow starts a gist room. **notifications.direct** — a direct message, a chat request, being added to a group.\n\n**chat.messagesFrom** (`no_one` | `everyone` | `verified`) governs EVERY direct message: POST /conversations (starting a chat) and POST /conversations/{id}/messages into an existing 1:1. Refused with 403 `MESSAGES_RESTRICTED`, `details: { messagesFrom }`. Somebody always gets through when the recipient has sent a message in that conversation (people you message can answer you), when `allowHouseMembers` is on and they share a group, or when `allowPastAudience` is on and they watched one of the recipient’s gist rooms. A block is refused separately, as before (403 FORBIDDEN).","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"notifications":{"type":"object","additionalProperties":false,"properties":{"friendsRooms":{"type":"boolean"},"direct":{"type":"boolean"}}},"privacy":{"type":"object","additionalProperties":false,"properties":{"locationPrecision":{"type":"string","enum":["city_region_country","region_country","country","continent"]},"showListening":{"type":"boolean"},"personalizeByPlace":{"type":"boolean"}}},"chat":{"type":"object","additionalProperties":false,"properties":{"messagesFrom":{"type":"string","enum":["no_one","everyone","verified"]},"allowHouseMembers":{"type":"boolean"},"allowPastAudience":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"The whole settings object after the change","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfileSettings"}}}}}},"400":{"description":"VALIDATION_ERROR — unknown key, value outside the choices, or empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/photos":{"get":{"summary":"The caller’s own profile photo gallery","description":"The same list GET /profiles/{username}/photos returns, for a caller who may not have a username yet.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"The gallery, position order","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfilePhotoList"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"post":{"summary":"Add a photo to the caller’s profile gallery (images only, up to 12)","description":"Upload the image through POST /uploads/presign + /uploads/complete first (image content types, maxImageBytes), then send back the URL you were given. The URL must be byte-for-byte one this service issued for the CALLER’s own upload: an arbitrary address or somebody else’s upload is 403 FORBIDDEN, a video or audio upload is 400. The new photo goes after the others.\n\n**Cap** — 12 photos. The 13th is 409 CONFLICT with `message: \"You can add up to 12 photos\"` and `details: { limit: 12 }`. Adding the same URL twice is also 409.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","maxLength":2048}}}}}},"responses":{"201":{"description":"The added photo","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfilePhoto"}}}}}},"400":{"description":"VALIDATION_ERROR — not a URL, or not an image","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — not a URL this service issued for the caller","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — the gallery holds 12 already, or this photo is already in it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/photos/order":{"patch":{"summary":"Reorder the caller’s gallery","description":"`ids` must name EVERY photo in the gallery exactly once, in the new order; positions become 0..n-1. A partial list, a repeated id or an id that is not the caller’s is 400 and changes nothing. Answers with the reordered gallery.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":12,"items":{"type":"string","format":"uuid"}}}}}}},"responses":{"200":{"description":"The gallery in its new order","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfilePhotoList"}}}}}},"400":{"description":"VALIDATION_ERROR — ids is not every photo exactly once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/photos/{id}":{"delete":{"summary":"Remove a photo from the caller’s gallery","description":"404 for a photo that is not the caller’s, exactly as for one that does not exist. The remaining photos keep their order.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Photo not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/profiles/{username}/photos":{"get":{"summary":"A profile’s photo gallery","description":"Public, like the profile: `username` may also be the profile id (Privy DID), and an unknown profile is 404. The profile read hides nothing from a blocked viewer today, so neither does this. Position order; an empty gallery is `items: []`.","tags":["market-square"],"security":[{},{"market-square_bearerAuth":[]}],"parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The gallery, position order","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfilePhotoList"}}}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/profile-views":{"get":{"summary":"Who viewed my profile — the last 90 days, most recent first","description":"One line per person, with the time of their most recent view. `total` is the number of people in the window and is on EVERY page. The list reflects the rules as they stand now: somebody who has since turned on private browsing, or where a block now exists in either direction, is left out of both the rows and the total.\n\n**Reciprocal**: while the CALLER has `privateBrowsing` on, this is refused with 403 FORBIDDEN (message: \"Turn off private browsing to see who viewed your profile\"), and GET /me reports `profileViewCount: null`. Turning it off shows the list again; views recorded before were never lost.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"The caller’s viewers","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ProfileViewPage"}}}}}},"400":{"description":"VALIDATION_ERROR — limit above 50","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — the caller is browsing privately","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/bookmarks":{"get":{"summary":"The viewer's bookmarked posts (\"Arkmarks\"), newest-bookmarked first","description":"Returns the same paged FeedItem shape as the feed lanes so clients reuse their feed renderer. Cursor is `${bookmarkedAt}|${postId}` from the previous page.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Bookmark page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_FeedItem"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/posts/{id}/comments":{"post":{"summary":"Comment on a post","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":1000},"mentions":{"type":"array","maxItems":25,"items":{"$ref":"#/components/schemas/market-square_Mention"},"description":"Optional. Handles typed into `text` are resolved server-side anyway, so omitting this still mentions people — sending it is how a picker records exactly who was meant."},"parentId":{"type":"string","description":"Reply to a comment on this post. Send whichever comment was TAPPED — if it is itself a reply, the new comment is filed under that reply’s top-level parent and `replyToCommentId` records what was answered, so the thread stays one visible level deep and the client never has to work out which comment is top-level. A parent on another post is refused with 404."}}}}}},"responses":{"201":{"description":"The comment","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Comment"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Comments page","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Comment page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Comment"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Post not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/comments/{id}/replies":{"get":{"summary":"One comment's replies (oldest first)","description":"A conversation reads DOWNWARD, so this is oldest-first — the opposite of the thread list, which is newest-first. Public with optional auth, like the comments list; likedByMe appears only for a signed-in caller.","tags":["market-square"],"security":[{},{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Reply page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Comment"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Comment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/comments/{id}/like":{"post":{"summary":"Like a comment (idempotent)","description":"Liking twice is a no-op rather than an error, and returns the same count — a second tap cannot inflate the tally.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Like state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"liked":{"type":"boolean"},"likeCount":{"type":"integer"}}}}}}}},"404":{"description":"Comment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Unlike a comment (idempotent)","description":"Unliking something you never liked is a no-op returning the current count. The tally can never go below zero.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Like state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"liked":{"type":"boolean"},"likeCount":{"type":"integer"}}}}}}}},"404":{"description":"Comment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/comments/{id}":{"get":{"summary":"One comment (the notification deep link, and a comment permalink)","description":"A `comment_reply` notification carries the REPLY’s id, and a reply is not on the post’s top-level page — so a client holding that id alone cannot tell which thread to expand. Read the comment for its `parentId` (expand that thread) and its own id (scroll and highlight). 404 once the comment is deleted.","tags":["market-square"],"security":[{},{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Comment","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Comment"}}}}}},"404":{"description":"Comment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Delete a comment (author, or the POST author)","description":"The comment's own author may delete it, and so may the author of the POST — a person is responsible for what sits under their own post. Anyone else gets 403. Deleting a reply decrements its parent's replyCount, and deleting any comment decrements the post's commentCount.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}}}},"403":{"description":"Not yours to delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Comment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/feed":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"The feed — lanes for-you | following | live | platform (first page Redis-cached 30s per viewer)","tags":["market-square"],"parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":200},"description":"Free-text filter over post text. Blank/absent means NO filter. This exists so BROWSE and NARROW are one list with ONE cursor: falling through to GET /search when the user types would page differently, silently changing the shape of the list they are already scrolling. Wildcards are escaped, so `%` cannot match everything. Composes with `lane`, `topics` and `mediaKind`. Lanes that serve no posts (`live`, `platform`) return an EMPTY page under it — ranking streams by relevance belongs to GET /search. It is part of the first-page cache key, so a searched page is never served to a browse request."},{"name":"topics","in":"query","schema":{"type":"string","example":"gaming,crypto"},"description":"Comma-separated topic keys (GET /topics). FILTERS to content carrying ANY of them; omit for everything. Distinct from the viewer's saved interests, which BOOST for-you ordering rather than filtering it."},{"name":"mediaKind","in":"query","schema":{"type":"string","example":"image,video"},"description":"Comma-separated media kinds (`image`, `video`) — the Explore grid's \"pictures and video\" filter. FILTERS to posts whose mediaKind is one of them; a post with no media never matches. Composes with `lane` and `topics`, and is part of the first-page cache key, so a filtered page is never served to an unfiltered request. Lanes that serve no posts (`live`, `platform`) return an EMPTY page under this filter rather than stream/event cards; `reels` intersects with it (`mediaKind=image` alone is therefore empty there). Unknown values are a 400, never silently ignored."},{"name":"lane","in":"query","schema":{"type":"string","enum":["for-you","following","live","platform","trending","reels"]},"description":"ALL lanes serve `kind: update` only — a story is a separate 24h object with its own rail (GET /stories) and never appears here. for-you (ranking weights: followed author +10000, saved-interest match +2500, engagement = likes + 2x comments, age -1/hour — so a saved interest outranks engagement but never a follow, and BOOSTS rather than filters), following (followed authors, first page merges reposts by followed users with repostedBy attribution), live (live streams + activities ≤24h), platform (cross-service activity), trending (7-day engagement velocity — cursor is a rank offset), reels (video posts newest-first)."},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Feed page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_FeedItem"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/search":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Discover/Explore search across people, posts, streams and ARK Store items","description":"Public; authentication is OPTIONAL and only enriches viewer state (isFollowing, likedByMe, bookmarkedByMe, repostedByMe). The response carries `topicFilter` and `mediaKindFilter`, each naming the kinds the filter could NOT act on, so a client never mistakes an excluded category for an empty one. A blank or whitespace-only `q` returns an EMPTY result set, never everything. Wildcards in `q` are escaped so `%`/`_` cannot match every row. Results of different kinds are interleaved so `type=all` shows a mix; the cursor is an offset into the merged ranked list. People rank prefix matches above substring matches, then by follower count; streams order live → scheduled → ended.","tags":["market-square"],"parameters":[{"name":"topics","in":"query","schema":{"type":"string","example":"gaming,crypto"},"description":"Comma-separated topic keys (GET /topics). FILTERS results to content carrying ANY of them. People carry no topics, so a topic filter excludes the people and products groups entirely rather than returning them unfiltered."},{"name":"mediaKind","in":"query","schema":{"type":"string","example":"image,video"},"description":"Comma-separated media kinds (`image`, `video`). Only POSTS carry a media kind, so this filter narrows post hits and EXCLUDES the people, streams and products groups entirely — the response says so in `mediaKindFilter` rather than returning them unfiltered. Same syntax and validation as on GET /feed."},{"name":"q","in":"query","schema":{"type":"string","maxLength":200}},{"name":"type","in":"query","schema":{"type":"string","enum":["all","people","posts","streams","products"],"default":"all"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Mixed search results","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_SearchItem"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/categories":{"get":{"summary":"Explore Categories tile counts","description":"Counts only what this service owns (posts, live streams, ARK Store items, creator profiles). Real-world assets and prediction markets are owned by other services, so their tiles return count: null — render as blank/em-dash, never as 0. They become real once those domains publish counts we project locally or the gateway aggregates.","tags":["market-square"],"responses":{"200":{"description":"Category tiles","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/market-square_CategoryCount"}}}}}}}}}},"/v1/market-square/conversations":{"post":{"summary":"Open (or fetch) the 1:1 conversation with another profile","description":"Idempotent: a pair maps to exactly one conversation regardless of who opens it, and a repeat never re-notifies. The response carries requestState — accepted when the recipient follows you, pending otherwise, in which case it is a chat REQUEST: it appears only under Gist Requests for them and adds nothing to their unread badge until they accept. 400 when messaging yourself; 403 when either party has blocked the other (identical either way, so the response cannot be used to detect a block).","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId"],"properties":{"userId":{"type":"string","description":"Peer's profile id"}}}}}},"responses":{"201":{"description":"The conversation","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"400":{"description":"Cannot message yourself","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Blocked in one direction or the other","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/conversations":{"get":{"summary":"Conversation inbox — most recently active first","description":"One endpoint behind the chat inbox’s four tabs: All = no kind; Gists = kind=direct; Houses = kind=group; Gist Requests = state=pending. state DEFAULTS to accepted, so a pending request can never appear in the ordinary inbox because a caller omitted the parameter.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["direct","group"]},"description":"Omit for both kinds (the All tab)."},{"name":"state","in":"query","required":false,"schema":{"type":"string","enum":["pending","accepted"],"default":"accepted"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Inbox page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ConversationSummary"}},"nextCursor":{"type":"string","nullable":true},"totalUnread":{"type":"integer","description":"GLOBAL unread message count across ALL ACCEPTED conversations (not page-scoped) — drives the Chat nav badge. Pending requests are excluded: a stranger must not be able to put a number on somebody’s nav."},"pendingRequests":{"type":"integer","description":"GLOBAL count of chat requests awaiting the caller — the Gist Requests tab."}}}}}}}},"400":{"description":"Unknown kind or state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/groups":{"post":{"summary":"Create a group conversation","description":"The caller becomes the owner. A group is never gated behind a request — you are added by somebody, and your remedy is to leave. Members the caller has blocked, or who have blocked the caller, are REFUSED rather than silently dropped.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","memberIds"],"properties":{"title":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":500,"description":"What the room is for. Optional — a group is usable with a name alone."},"imageUrl":{"type":"string","format":"uri","maxLength":2000,"description":"The room’s picture. MUST be a URL this service issued from its own upload path (POST /uploads or the presign pair) — the same verification a message attachment goes through, because a group image is rendered to every member exactly as a photo in a thread is. 403 when the upload is somebody else’s, 400 when it is not a URL this service would have minted or is not an image."},"memberIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":499,"description":"Everyone except the caller, who is added as the owner. A group holds at most 500 people in total, so at most 499 ids here."}}}}}},"responses":{"201":{"description":"The group","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"400":{"description":"Empty name, no other members, too many, or an unusable picture","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"A named member is blocked in one direction or the other","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/geo/reverse":{"post":{"summary":"A named place from coordinates — city and region only","description":"Backs the \"Use my location\" control on the profile form. GATED, deliberately: every usable geocoder is either keyed or carries a usage policy, so the lookup cannot happen in the browser — a key there is a key published in the bundle, and a policy is ours to stay inside rather than each visitor’s. Rate limited per user, because one tap here is one request to a third party we do not pay for and do not control. IT WRITES NOTHING: the place comes back, the person sees it, and THEY decide whether to save it with PATCH /me, which is what makes this a convenience button rather than the app quietly recording where somebody is. THE RESPONSE IS THE WHOLE CONTRACT — a city and a region, and nothing else. No country, no street, no postcode, no formatted address, and the coordinates are never echoed back. That narrowness IS the privacy property: a caller cannot store what the route will not return. The coordinates are not persisted and not written to any log line, and there is no distance field anywhere in this API — a city somebody publishes about themselves is a fact they chose to share; a distance to a stranger is their position recomputed every time you look. 404 means the provider answered and recognised no place there (mid-ocean, a point with no locality) and is a real answer; 502 SERVICE_UNAVAILABLE means we could not ask — a deployment with no provider configured returns that rather than a null, so nobody is told their own city does not exist.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["latitude","longitude"],"properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180}}}}}},"responses":{"200":{"description":"The place, and only the place","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["city","region"],"properties":{"city":{"type":"string"},"region":{"type":"string"}}}}}}}},"400":{"description":"VALIDATION_ERROR — not a coordinate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"No place found there (code NO_PLACE_FOUND) — a real answer, not a failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"SERVICE_UNAVAILABLE — could not ask the provider, or none is configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/discover":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Public houses a reader could join","description":"The directory behind \"Join a community\". Lists GROUPS whose `visibility` is `public`, biggest first, so the section opens on the communities worth joining rather than on insertion order. PUBLIC with optional auth: Home shows this to signed-out readers, and a directory that needs an account to show what you might join has the order backwards. When a caller IS authenticated, groups they are already in are excluded — a Join House button on a house you are in is the surest way to make the control look broken. It returns a DOORPLATE, never content: `title`, `imageUrl`, `description`, `memberCount` and a short preview roster, with `lastMessage` null and `unreadCount` 0 on every row. This is the one conversation read that answers for non-members, so it must never become a way to read one. Page with `cursor` (a `memberCount|id` pair) and `limit` (1-50, default 20); join a listed house with POST /conversations/{id}/join.","tags":["market-square"],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"Public houses","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ConversationSummary"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}":{"get":{"tags":["market-square"],"summary":"What a shared link is inviting you to (readable by a NON-member)","description":"The invite preview behind a shared group link. Every other read of a conversation is membership gated, which is right for messages and wrong for an invite — somebody opening a link is by definition not in the group yet. DELIBERATELY THIN: an identity, a picture, a size and whether you may join. No messages and no member list; a link lets you see what you are joining, never read it first. `optionalAuth`, because a link is often opened before signing in. A PRIVATE group still previews and reports `canJoin: false` — the same call `POST /join` already makes, which explains rather than 404s because somebody handed the reader the id; what is protected is getting IN. A DIRECT conversation is NOT previewable: a non-participant gets 404, since a preview would answer \"are these two people talking\" to anybody holding an id.","security":[{},{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The invite preview","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["id","title","description","imageUrl","memberCount","visibility","viewerIsMember","canJoin"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string","nullable":true,"description":"Null when the group was never named. Fall back in the client — never to \"Unknown\"."},"description":{"type":"string","nullable":true},"imageUrl":{"type":"string","nullable":true},"memberCount":{"type":"integer"},"visibility":{"type":"string","enum":["public","private"]},"viewerIsMember":{"type":"boolean","description":"False for a signed-out reader rather than unknown."},"canJoin":{"type":"boolean","description":"Whether POST /conversations/{id}/join would be ACCEPTED for this viewer. Resolved server-side because the client cannot work it out: it depends on visibility, on membership, on whether the room is full, and on whether the owner has blocked them — the last of which is deliberately invisible to the client and only ever collapses this to false. Draw Join from THIS, not from `visibility`: a link that offers Join and is then refused is worse than one that says the room is closed."}}}}}}}},"404":{"description":"No such conversation, or a direct conversation the caller is not in","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"delete":{"summary":"Delete a chat — for YOU only","description":"Per person, never per conversation. A thread has two sides and a group has many, so removing the row would reach into other people’s inboxes and destroy a conversation they never asked to lose. Instead this stamps the caller’s own participant row: the thread leaves THEIR inbox and every message before this moment stops being returned to THEM. Everybody else’s copy is untouched, read receipts included. It is NOT leaving: the caller stays a member, and a new message brings the thread back carrying only what arrived after — which is why it is safe to offer without a \"this cannot be undone\" dialog, because it can be undone by anyone writing again. Idempotent: deleting an already-deleted chat just moves the watermark forward. To actually leave a group, remove yourself from its members.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted for you","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"patch":{"summary":"Edit a group’s profile — name, description, picture (owner only)","description":"ONE call for the three, because they are one form: three endpoints would be three round trips that can half-fail, leaving a group named after the edit but described before it. Every field is optional and at least one is required. On description and imageUrl an ABSENT key leaves the field alone while an explicit null CLEARS it — that distinction is how a picture is removed.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"At least one field is required.","properties":{"title":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":500,"nullable":true,"description":"null clears it. A blank string is read as a clear, not as a description."},"imageUrl":{"type":"string","format":"uri","maxLength":2000,"nullable":true,"description":"null removes the picture. Otherwise it must be a URL this service issued for the CALLER, and an image — same verification a message attachment goes through."}}}}}},"responses":{"200":{"description":"The updated group","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"400":{"description":"Empty name, not a group, or an unusable picture","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant, or not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/members":{"get":{"summary":"The conversation roster, with each member’s role","description":"The full list. An inbox row carries at most four profiles, which is right for a stack of avatars and wrong for a group’s own header.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Members","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ConversationMember"}},"title":{"type":"string","nullable":true,"description":"The group's name — null on a direct conversation. Sent with the roster because the one surface that needs it is already asking for the members: a gist room's header names the house it belongs to, and its member grid IS this list."},"lastActiveAt":{"type":"string","nullable":true,"description":"Newest lastSeenAt across the members OTHER than the caller — the group header’s \"Active 3d ago\", beside memberCount. NULL when nobody else has ever been observed."}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"post":{"summary":"Add people to a group (any member may)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["memberIds"],"properties":{"memberIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":499,"description":"People to add. 400 when the group would end up over 500 people, counting everybody already in it."}}}}}},"responses":{"200":{"description":"The group","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"400":{"description":"Not a group, or the group is full","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant, or a named member is blocked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation or profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/members/{profileId}":{"delete":{"summary":"Leave a group, or remove somebody from it","description":"One route for both, because they are the same operation with a different subject. Anybody may remove THEMSELVES — a group you cannot leave is a group anybody can trap you in — and only the owner may name somebody else. The last member out deletes the group.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"400":{"description":"Not a group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant, or not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/notification-settings":{"get":{"summary":"The caller's notification settings for one group","description":"Members only: anybody else, and a direct conversation, is 404. Every member starts at `{ messages: \"all\", rooms: \"all\" }`. The same object rides on each group row of GET /me/conversations as `notificationSettings`.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The settings","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_GroupNotificationSettings"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found (or the caller is not a member of this group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"put":{"summary":"Change them — either or both, answers the whole settings","description":"**messages** (`all` | `leaders_and_friends` | `none`) governs `message` notifications for this group. **rooms** (`all` | `leaders_and_friends` | `directed` | `none`) governs `house_room` (a member opened a gist room from the group) and, for rooms in this group, `speaker_request`.\n\n`leaders_and_friends` = the group owner and admins, plus anyone the member follows. `directed` = only room notifications that name you (`speaker_request`); it hears no room openings. `none` hears nothing, `speaker_request` included. Strict: an unknown key, a value outside the choices, or an empty body is a 400.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"messages":{"type":"string","enum":["all","leaders_and_friends","none"]},"rooms":{"type":"string","enum":["all","leaders_and_friends","directed","none"]}}}}}},"responses":{"200":{"description":"The whole settings after the change","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_GroupNotificationSettings"}}}}}},"400":{"description":"VALIDATION_ERROR — unknown key, value outside the choices, or empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found (or the caller is not a member of this group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/members/{profileId}/role":{"put":{"summary":"Make a group member an admin, or an admin a member (owner only)","description":"Roles are owner / admin / member. ADMINS edit the group name, description and picture, remove MEMBERS (never the owner or another admin), and make, list and revoke invite links, private groups included. Only the OWNER changes roles, changes visibility, and hands the group over. The owner’s own role is not changed here (400): use POST /conversations/{id}/transfer-ownership. When the owner leaves, the group passes to the longest-standing admin, or the longest-standing member if there is none.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["role"],"properties":{"role":{"type":"string","enum":["admin","member"]}}}}}},"responses":{"200":{"description":"The new role","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"profileId":{"type":"string"},"role":{"type":"string","enum":["admin","member"]}}}}}}}},"400":{"description":"Not a group, or the target is the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — only the group owner can change roles (or the caller is not a member)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Member not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/transfer-ownership":{"post":{"summary":"Hand the group to another member (owner only)","description":"The named member becomes the owner and the previous owner stays on as an ADMIN, in one write, so the group never has zero or two owners.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["profileId"],"properties":{"profileId":{"type":"string"}}}}}},"responses":{"200":{"description":"Who owns it now","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"ownerId":{"type":"string"},"previousOwnerId":{"type":"string"}}}}}}}},"400":{"description":"Not a group, or the caller already owns it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — only the group owner can hand it over","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Member not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/join":{"post":{"summary":"Join a PUBLIC group","description":"What makes a group's `visibility` mean something rather than being a stored preference. Succeeds on a public group; refuses a private one with 403 (`ask a member to add you` — the link's existence is not the secret, entry is). Idempotent for somebody already in it. A direct conversation cannot be joined. The owner's blocks still apply: a public door is not a bypass.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The group","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"400":{"description":"Not a group, or the group is full","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"The group is private, or you are blocked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/invites":{"post":{"summary":"Make a shareable invite link for a group","description":"A link that can go anywhere (WhatsApp, X, a text) and opens the group, PRIVATE groups included. Any member of a public group may make one; on a private group only the owner (403 otherwise). A non-member gets 404.\n\nLives `expiresInHours` (default 168 = a week, max 720 = 30 days) and may be capped with `maxUses` (1..500; omitted = uncapped). The `token` is 128 random bits, URL-safe, 22 characters: build the share URL on the client, e.g. `/join/{token}`.\n\nA link stops working when its creator leaves, or when the group turns private and they are not the owner.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"expiresInHours":{"type":"integer","minimum":1,"maximum":720},"maxUses":{"type":"integer","minimum":1,"maximum":500}}}}}},"responses":{"201":{"description":"The invite link","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ConversationInvite"}}}}}},"400":{"description":"VALIDATION_ERROR — expiresInHours or maxUses out of range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — only the owner can make a link for a private group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found (or the caller is not a member)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"get":{"summary":"The group’s working invite links","description":"Links that still work (not revoked, expired or used up), newest first. The owner sees every one; any other member sees the links they made. A non-member gets 404.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Working links","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ConversationInvite"}}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found (or the caller is not a member)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/invites/{token}":{"delete":{"summary":"Revoke an invite link","description":"Its creator or the group owner. After this the token answers exactly like one that never existed (404). Anybody else, or a link already revoked, is 404.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Revoked"},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Invite not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/invites/{token}":{"get":{"summary":"Open an invite link: what group it is, and whether it still works","description":"optionalAuth, because a link is usually opened before signing in. The same preview GET /conversations/{id} gives, private groups included, plus `valid`, `reason` and `expiresAt`. `canJoin` is resolved for THIS link and viewer: false when signed out, already a member, the link is expired or used up, the group is full, or a block exists with the owner or the person who made the link.\n\nAn unknown or revoked token, or one whose creator can no longer share it, is 404. An expired or used-up link still answers 200 with `valid: false` and the reason, so the page can say \"ask for a new link\".","tags":["market-square"],"security":[{},{"market-square_bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The group and the link","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_InvitePreview"}}}}}},"404":{"description":"Invite not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/invites/{token}/accept":{"post":{"summary":"Join a group through an invite link","description":"Joins the group, PRIVATE groups included. Idempotent: somebody already in gets the group back and no use is spent. Two people racing for the last use of a capped link cannot both get in.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The group joined","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"400":{"description":"This group is full","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — a block with the owner or with the person who made the link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Invite not found (unknown, revoked, or its creator can no longer share it)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"410":{"description":"GONE — expired or used up; `details.reason` is `expired` or `used_up`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/accept":{"post":{"summary":"Accept a chat request","description":"Only the person who did NOT ask may accept — otherwise a sender could accept their own request into the recipient’s inbox, which is the whole thing the gate prevents. Replying to a request also accepts it, so this is for accepting without answering.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The accepted conversation","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Conversation"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant, or you are the one who asked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/decline":{"post":{"summary":"Decline a chat request","description":"Deletes the conversation and its messages, and tells the sender nothing — a decline that reports itself is a decline nobody will use. The pair is free to start again; blocking is the separate, stronger remedy.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Declined and removed"},"400":{"description":"Not a request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant, or you are the one who asked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/messages":{"get":{"summary":"Messages in a conversation, newest first (participants only)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Message page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ConversationMessageView"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"post":{"summary":"Send a message (participants only; rate limited)","description":"The body carries text, an attachment, or both — a message with neither is a 400. An attachment is sent as `media.url`, and it MUST be a URL this service issued: upload first via POST /uploads or the presign pair, then send the resulting `publicUrl`. A URL from anywhere else is refused (403 when it is not the caller’s own upload, 400 when it is not a URL this service would have minted), so a private thread can never be made to load an arbitrary remote asset. There is no `media.kind` field — the kind is derived from the stored object, so a client cannot label a clip as a voice note.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"At least one of `text` and `media` is required.","properties":{"text":{"type":"string","maxLength":2000},"media":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"The `publicUrl` from POST /uploads/complete or POST /uploads — nothing else is accepted."},"width":{"type":"integer","minimum":1,"maximum":100000},"height":{"type":"integer","minimum":1,"maximum":100000},"durationSeconds":{"type":"integer","minimum":1,"maximum":86400,"description":"Audio and video only; a duration on an image is a 400."}}}}}}}},"responses":{"201":{"description":"The message","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_ConversationMessage"}}}}}},"400":{"description":"Nothing to send, or an attachment this service did not issue","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant, or media belonging to somebody else","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/conversations/{id}/read":{"post":{"summary":"Mark the peer's messages read","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Remaining unread in this conversation","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"unreadCount":{"type":"integer"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not a participant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/realtime/grant":{"get":{"tags":["market-square"],"summary":"Mint the WebSocket subscribe grant for the caller","parameters":[{"name":"conversationIds","in":"query","required":false,"schema":{"type":"string","maxLength":20000},"description":"Comma-separated conversation ids to make sure the grant covers — the room the client has just opened, typically. These take priority over the recency fill, which matters because reading an old room does NOT make it recently active, so recency alone can never reach it. Membership is checked: ids the caller is not in are dropped silently rather than refused, so the response cannot be used to discover whether a room exists. At most 100 are looked up; the signed list is still capped."}],"description":"A short-lived signed permit naming the conversations this user may subscribe to on the WebSocket gateway (ADR-0009). Present it to the gateway as `{\"type\":\"subscribe\",\"topics\":[\"market-square:conversation:<id>\"],\"grant\":\"<token>\"}`, or on its own as `{\"type\":\"grant\",\"grant\":\"<token>\"}` to refresh before it expires. The socket must ALSO be authenticated as the same user — a grant is membership, not a login. `conversationIds` is CAPPED (most recently active first); rooms beyond the cap keep polling — pass `?conversationIds=` to pin the room on screen into the grant so it is not left behind by a busier one. Answers SERVICE_UNAVAILABLE (HTTP 502 by this platform’s convention — match error.code, not the status) when realtime is not configured, which is a working deployment: the client simply keeps its poll.","security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"The grant","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","required":["token","expiresAt","conversationIds"],"properties":{"token":{"type":"string","description":"Opaque to the client. Do not parse it; read expiresAt."},"expiresAt":{"type":"integer","description":"Unix SECONDS. Refresh before this or conversation topics stop being issued."},"conversationIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Exactly the rooms this grant covers. Subscribing to anything else is refused by the gateway."}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"SERVICE_UNAVAILABLE — realtime is not configured here; keep polling","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/unread":{"get":{"summary":"Unread badge counts for the primary nav (one call, both badges)","description":"messages = unread messages across all ACCEPTED conversations; notifications = unread notifications; chatRequests = conversations awaiting the caller’s acceptance. All three are global, not page-scoped. Pending requests are deliberately absent from `messages`: a stranger must not be able to put a number on somebody’s nav.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"Badge counts","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"messages":{"type":"integer"},"notifications":{"type":"integer"},"chatRequests":{"type":"integer"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/notifications":{"get":{"summary":"Notifications inbox (hydrated actor + subject, unreadCount)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}},{"name":"group","in":"query","required":false,"schema":{"type":"string","enum":["social","money","rooms","chat","account"]},"description":"Filter pill. Omit for everything — there is no \"all\" member. Each row also carries its own group, so the client never re-derives the mapping. unreadCount is NOT filtered: the badge counts what is waiting, not what is on screen."}],"responses":{"200":{"description":"Notification page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Notification"}},"nextCursor":{"type":"string","nullable":true},"unreadCount":{"type":"integer"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/notifications/read":{"post":{"summary":"Mark notifications read (omit ids to mark all)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":200}}}}}},"responses":{"200":{"description":"Remaining unread","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"unreadCount":{"type":"integer"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/reports":{"post":{"summary":"Report content or a profile","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_CreateReportRequest"}}}},"responses":{"201":{"description":"Report filed","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}}}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams":{"get":{"summary":"Stream discovery","security":[{},{"market-square_bearerAuth":[]}],"description":"Also the lookup for \"who is broadcasting this?\" — pass `deepLinkRef` with `status=live` to find the existing broadcast(s) of a game/match so a second participant joins it as a co-publisher (via the speaker-request flow) instead of starting a rival stream. ALWAYS a list: the same ref can legitimately be broadcast by several creators at once, so never assume exactly one.","tags":["market-square"],"parameters":[{"name":"topics","in":"query","schema":{"type":"string","example":"gaming,crypto"},"description":"Comma-separated topic keys (GET /topics). FILTERS to content carrying ANY of them; omit for everything. Distinct from the viewer's saved interests, which BOOST for-you ordering rather than filtering it."},{"name":"deepLinkRef","in":"query","schema":{"type":"string","maxLength":512},"description":"Exact match (not prefix or substring) on deepLink.ref — the lookup for \"who is broadcasting this?\". The result is a LIST and may legitimately contain SEVERAL concurrent broadcasts of one ref (a global draw covered by multiple creators), so never assume exactly one. Unknown refs return an empty list, not a 404. Combine with status=live for the join-an-existing-broadcast flow. Indexed for the hot path."},{"name":"status","in":"query","schema":{"type":"string","enum":["live","scheduled","ended"]}},{"name":"category","in":"query","schema":{"type":"string","enum":["worldstreet","music","podcast","gaming","other","house"],"description":"A `house` is an AUDIO-ONLY room. It is a category rather than a separate entity because a house is the same room, the same speaker requests and the same chat — only the media differs. It is load-bearing rather than descriptive: the token signer reads it and grants MICROPHONE only, so a house cannot publish a camera or a screen share even from a patched client."}},{"name":"kind","in":"query","schema":{"type":"string","enum":["broadcast","room"],"description":"WHAT KIND of live thing, as opposed to what it is about. `broadcast` is every stream EXCEPT a house; `room` is a house (a gist room). Use `kind=broadcast` for a Live/watch surface: `category` can NAME a house but cannot exclude one — \"not a house\" is not a taxonomy value — so a live list without this returns audio rooms beside video streams, offering something to watch that has nothing to watch and its own page to join. It COMPOSES with `category` rather than replacing it, so `kind=broadcast&category=house` correctly matches nothing. A future audio category joins `room` by changing one predicate here rather than every caller."}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Stream page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Stream"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}},"post":{"summary":"Create a stream (role creator|worldstreet)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_CreateStreamRequest"}}}},"responses":{"201":{"description":"The scheduled stream — `scheduledAt` is always present; omitting it on the request means \"now\"","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Stream"}}}}}},"400":{"description":"VALIDATION_ERROR (ticketed requires ticketPriceKash > 0)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — role gate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}":{"patch":{"summary":"OWNER: edit a stream in place (including mid-broadcast)","description":"Presentation fields plus rescheduling. Status, ingest, replay and viewership are lifecycle state and are not patchable; pricing and visibility are deliberately immutable once the stream exists, so a ticket cannot change meaning after it was bought. `deepLink: null` clears the link. `scheduledAt` may be MOVED but never cleared — a scheduled stream with no start time cannot be rendered, sorted or reminded on, and the database refuses that combination. Ended/cancelled streams return 409.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","maxLength":200},"scheduledAt":{"type":"string","format":"date-time","description":"Move the start time. Null is rejected — see above."},"description":{"type":"string","maxLength":2000},"category":{"type":"string","enum":["worldstreet","music","podcast","gaming","other","house"]},"thumbnailUrl":{"type":"string","format":"uri"},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true}}}}}},"responses":{"200":{"description":"The updated stream","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Stream"}}}}}},"400":{"description":"No fields supplied / invalid value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the stream owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Stream has ended or was cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Stream detail (+ live viewerCount, myTicket when authed)","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The stream","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StreamDetail"}}}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/go-live":{"post":{"summary":"Owner starts (or rejoins) the stream — returns provider ingest credentials","description":"Idempotent for the owner while the stream is live: a re-POST returns the same { stream, ingest } shape with a freshly signed publisher roomToken and best-effort ingress reuse — no state change and no duplicate stream.live event (it is emitted only on the scheduled→live transition). Ended/cancelled streams still 409.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stream + ingest","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"stream":{"$ref":"#/components/schemas/market-square_Stream"},"ingest":{"$ref":"#/components/schemas/market-square_StreamIngest"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Not in scheduled state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"PROVIDER_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/end":{"post":{"summary":"Owner ends the stream — replayUrl stored when the provider returns a recording","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The ended stream","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Stream"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Not live","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"PROVIDER_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/tickets/quote":{"post":{"summary":"Quote a ticket tier","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_TicketTierRequest"}}}},"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_TicketQuote"}}}}}},"400":{"description":"Public stream / missing tier","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/tickets":{"post":{"summary":"Buy a ticket: pending → KASH rail debit (idempotency key = ticket id) → confirmed + immutable ledger row + event. Re-POST returns the existing confirmed ticket.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_TicketTierRequest"}}}},"responses":{"201":{"description":"The confirmed ticket","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Ticket"}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"402":{"description":"PAYMENT_FAILED — rail declined; ticket marked failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Purchase already in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"PROVIDER_ERROR — rail unreachable; ticket stays pending for reconciliation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/following/rooms":{"get":{"summary":"Rooms your people are in","description":"Live gist rooms the caller may enter, each with the people they follow who are listening in it right now: the room with most of them first, then the busiest. Counts only people whose \"Visibility on Space\" is on, never a room’s host, and only rooms GET /streams would show the caller (a private room only to its members). BOUNDED: it reads the newest 100 live rooms and the most recent 200 sessions in each, so somebody who joined a very large room early can be missed; nobody is ever shown who is not there. An empty array for somebody who follows nobody.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"Rooms","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/market-square_FollowingRoom"}}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/tickets":{"get":{"summary":"Own tickets with stream summaries","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"Tickets","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Ticket"}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/playback-token":{"post":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Short-lived signed playback grant (≤5 min TTL). Ticketed streams require a confirmed ticket; VIP early access applies only when the economics gate is live. Works for live and replay. The LiveKit participant identity is the user id for signed-in viewers, and a fresh random `anon-<uuid>` for each anonymous grant — LiveKit evicts duplicate identities, so anonymous viewers must never share one. SUBSCRIBE-ONLY, with exactly one exception: a caller who holds an APPROVED speaker request on this live stream gets `canPublish: true` (CAMERA, MICROPHONE, SCREEN_SHARE, SCREEN_SHARE_AUDIO) on their SAME viewer identity. That is not a widening — it is the same condition POST /speaker-token already enforces — and it is what makes an approved guest survive a reload, a network drop, or this token simply expiring and being refetched. Approval alone only edits the participant that is connected at that moment; that grant dies with the connection, so without this the row said `approved` while LiveKit said `canPublish: false` and the guest could never get back on stage.","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The grant","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_PlaybackGrant"}}}}}},"403":{"description":"FORBIDDEN — no confirmed ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream/replay not found. Also the answer for a PRIVATE gist room the caller is not a member of, identically, so the id cannot confirm the room exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Not live and no replay","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/preview-token":{"post":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Hidden, listen-only grant to PREVIEW a live gist room from its card (hover). Same response shape as playback-token. The grant is subscribe-only (canPublish false, canPublishData false), HIDDEN (the previewer never appears in the room audience), carries no name and no metadata, lives 120 seconds, and its LiveKit identity is a fresh random `preview-<uuid>` - never the caller id, so previewing a room you are already in cannot evict your real connection. The preview player MUST NOT call POST /streams/{id}/heartbeat: viewerCount, the participants sample and watch time are fed by heartbeats, so a client that heartbeats would count itself. Heartbeats start only after joining with a real playback token. Visibility is identical to playback-token: a PRIVATE room the caller is not a member of answers 404, the same as a room that does not exist. Signed-in callers are rate-limited per minute.","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The preview grant","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_PlaybackGrant"}}}}}},"404":{"description":"No such stream, or a private room the caller is not a member of","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT: not a gist room, or not live","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/heartbeat":{"post":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"View-time heartbeat (1 counted beat per 15s per session; Redis-buffered, worker-flushed). Also renews the place this session holds in the live presence set that `viewerCount` reads - that renewal is NOT throttled, so a retried beat never drops the viewer out of the count. Anonymous allowed on public streams.","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_HeartbeatRequest"}}}},"responses":{"200":{"description":"Session state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"sessionId":{"type":"string"},"watchSeconds":{"type":"integer"}}}}}}}},"403":{"description":"Anonymous on ticketed stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"Beat throttled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/stats":{"get":{"summary":"OWNER: aggregate stream stats (live so-far or final after end)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The stats","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StreamStats"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/events":{"get":{"summary":"OWNER: host activity feed (ticket purchases + recent follows of the owner)","description":"Derived from existing tables: confirmed tickets for this stream plus the most recent follows RECEIVED by the owner (follows are not window-filtered to the stream). Newest first; cursor is the occurredAt ISO timestamp of the last item.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Event page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_HostStreamEvent"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/chat/{messageId}":{"delete":{"summary":"OWNER: soft-remove a chat message (excluded from GET afterwards)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"messageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"removed":{"type":"boolean"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream or message not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/bans":{"post":{"summary":"OWNER: mute a user in this stream chat (playback unaffected)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["userId"],"properties":{"userId":{"type":"string"}}}}}},"responses":{"200":{"description":"Banned","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"banned":{"type":"boolean"}}}}}}}},"400":{"description":"Cannot ban yourself","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/bans/{userId}":{"delete":{"summary":"OWNER: unmute a user in this stream chat","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Unbanned","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"banned":{"type":"boolean"}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/speaker-requests":{"post":{"summary":"Ask the host to speak (viewer)","description":"Idempotent: an already-open request is returned rather than duplicated, so a double-tap does not spam the host. Requires a LIVE stream; the host cannot request their own mic; muted viewers are refused; ticketed streams require a confirmed ticket, exactly like chat.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"The request","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_SpeakerRequest"}}}}}},"400":{"description":"You are the host","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Muted, or no ticket on a ticketed stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Stream is not live","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"get":{"summary":"HOST: the speaker queue (defaults to pending)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","denied","withdrawn","removed"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"The queue, each row with the requester hydrated","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/market-square_SpeakerRequest"},{"type":"object","properties":{"profile":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true}}}]}}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the stream owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/speaker-requests/me":{"get":{"summary":"The caller's own open request for this stream (null when none)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Own request or null","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"allOf":[{"$ref":"#/components/schemas/market-square_SpeakerRequest"}],"nullable":true}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/speaker-token":{"post":{"summary":"PUBLISHER token for an approved speaker (or the host)","description":"Returns { url, token, expiresAt } with canPublish: true. The grant covers CAMERA, MICROPHONE, SCREEN_SHARE and SCREEN_SHARE_AUDIO — a co-broadcaster (a second player, a commentator) must be able to show their board, not only their face. IDENTITY: this token is minted with `<userId>#speaker`, NOT the plain user id, so a guest who already holds a viewer connection can use it without the two connections evicting each other (LiveKit treats identity as unique and kicks the older one). PREFERRED PATH: you do not need this token at all — approval already grants publish rights on your EXISTING viewer connection via updateParticipant, and POST /playback-token re-mints that grant onto your viewer identity on every reconnect, so simply enabling the mic on the connection you have is the cheapest and safest option. Use this token only when joining fresh under a separate identity. Deliberately SEPARATE from POST /playback-token, which is subscribe-only for everyone EXCEPT an already-approved speaker — anonymous viewers and replay go through it too, so it must never grant publish on the strength of anything but an approved request. Only an `approved` speaker request qualifies; pending/denied/withdrawn/removed all return 403, and revoking a speaker also drops their LiveKit publish permission immediately. The same credentials are attached to GET /speaker-requests/me as joinUrl/joinToken once approved, so a guest can go live without a second call.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Publisher grant","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_PlaybackGrant"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not an approved speaker","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Stream is not live / has no media room","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/speaker-requests/{requestId}/{action}":{"post":{"summary":"Resolve a speaker request (approve | decline | remove | leave)","description":"Approval is how a CO-BROADCASTER joins: any authenticated user the host approves may publish (camera, microphone AND screen share) — being a viewer or a participant in whatever is being broadcast is NOT required, which is what makes commentator and guest joins work. approve/decline/remove are the HOST's actions; `leave` is the speaker stepping down themselves. Approval and removal move real LiveKit publish permissions via updateParticipant, applied to the live participant so no reconnect is needed — the database row alone grants nothing. The grant/revoke is applied to BOTH identities the guest could be connected under (`<userId>` for their viewer connection and `<userId>#speaker` for a publisher-token connection), so a removed speaker cannot keep the mic open on whichever one was missed. A speaker who is offline picks the grant up from their next token. Already-resolved requests return 409.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"requestId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","enum":["approve","decline","remove","leave"]}}],"responses":{"200":{"description":"The resolved request","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_SpeakerRequest"}}}}}},"400":{"description":"Unknown action","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the host (or not the speaker, for `leave`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream or request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Already resolved / already approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/streams/{id}/chat":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Chat history page (persisted for replay)","tags":["market-square"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Message page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_StreamMessage"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"post":{"summary":"Send a chat message (ticket-gated on ticketed streams; fanned out via ws-gateway)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":500}}}}}},"responses":{"201":{"description":"The message","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StreamMessage"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"No confirmed ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Stream not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/activities":{"post":{"summary":"Schedule an activity (feed pins upcoming/live ones)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_CreateActivityRequest"}}}},"responses":{"201":{"description":"The activity","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Activity"}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"get":{"summary":"Activities page","tags":["market-square"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["scheduled","live","completed","cancelled"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Activity page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Activity"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/activities/{id}":{"patch":{"summary":"Host edits a scheduled activity","description":"The same field set as POST /activities, all optional, mirroring PATCH /streams/{id}. `deepLink` is patchable AND nullable — the link was optional at creation (people announce before the thing exists), so `deepLink: null` must be able to clear it; an omitted key leaves it untouched.\n\nHost only. Editable ONLY while `scheduled`: a `cancelled` or `completed` activity returns CONFLICT, because editing one would resurrect a dead entry with fresh details while its status stayed stale — rescheduling a cancelled thing is a new activity, not an edit. `status` is deliberately NOT patchable: cancellation has its own endpoint and the lifecycle must not be settable by a free-form patch.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"properties":{"type":{"type":"string","enum":["game","stream","event"]},"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"startsAt":{"type":"string","format":"date-time"},"deepLink":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"description":"null clears the link."}}}}}},"responses":{"200":{"description":"The updated activity","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Activity"}}}}}},"400":{"description":"VALIDATION_ERROR — empty patch or bad field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the host","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Activity not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — activity is cancelled or completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/activities/{id}/cancel":{"post":{"summary":"Host cancels an activity","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The cancelled activity","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Activity"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not the host","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Activity not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/store/items":{"get":{"summary":"ARK Store catalogue (published items only)","tags":["market-square"],"parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":200},"description":"Free-text filter. Blank/absent means NO filter. This exists so BROWSE and NARROW are one list with ONE cursor: falling through to GET /search when the user types would page differently, silently changing the shape of the list they are already scrolling. Wildcards are escaped, so `%` cannot match everything. Matches name, tagline and description."},{"name":"category","in":"query","schema":{"type":"string","enum":["app","product","service"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Item page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_StoreItem"}},"nextCursor":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/store/items/{slug}":{"get":{"security":[{},{"market-square_bearerAuth":[]}],"summary":"Store item by slug (+ myOrder when authed)","tags":["market-square"],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The item","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StoreItem"}}}}}},"404":{"description":"Item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/store/items/{slug}/orders":{"post":{"summary":"Order/install an item: free ⇒ instant confirmed zero-price order + installCount++; paid ⇒ KASH rail flow (same as tickets). Idempotent per active order.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"The order","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StoreOrder"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"402":{"description":"PAYMENT_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Order already in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"PROVIDER_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/orders":{"get":{"summary":"Own store orders with item details","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"Orders","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/market-square_StoreOrder"}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/uploads/limits":{"get":{"summary":"The upload contract: per-kind size caps and the content-type allowlist","description":"PUBLIC and unauthenticated — the composer renders its file picker and pre-validates a chosen file before sign-in. Exists so clients STOP hard-coding these numbers: the caps and the allowlist were duplicated by hand in the web client, and raising one side alone gave users either a rejection after a long upload or a refusal of a file this service would have accepted. These are the same values enforced on POST /uploads, POST /uploads/presign, the `content-length-range` baked into the presigned POST policy, and the re-check on POST /uploads/complete — all four read one config, so they cannot drift from what is published here. Both caps are env-overridable (MEDIA_MAX_IMAGE_MB / MEDIA_MAX_VIDEO_MB), so a client must READ this rather than assume; keep a compiled-in copy only as a fallback for when the call fails. `maxVideoSeconds` is ADVISORY guidance for clients to check locally — it is not enforced anywhere on this side.","tags":["market-square"],"responses":{"200":{"description":"The upload contract","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_UploadLimits"}}}}}}}}},"/v1/market-square/uploads":{"post":{"summary":"Upload owned media (post images/video, avatars, stream covers). Multipart field `file`.","description":"PROXIED path — the bytes travel through this API. Prefer POST /uploads/presign for anything above ~4MB: a browser client behind a serverless function (Vercel and similar) hits a hard, non-configurable 4.5MB request-body limit long before our video cap, so video effectively CANNOT be uploaded this way. Images (jpeg/png/webp/gif, default ≤25MB) and video (mp4/webm, default ≤200MB) — the LIVE values are served by GET /uploads/limits; never hard-code them. The client filename is never trusted — the stored key is uploads/<userId>/<uuid>.<ext> with the extension derived from the content type. Rate limited (default 20/hour per user).","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":"The stored media","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_UploadResult"}}}}}},"400":{"description":"Unsupported type / too large / missing file / malformed or truncated multipart body (a broken body is the caller's error, never a 500)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"Media storage unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/uploads/presign":{"post":{"summary":"Authorise a DIRECT browser→storage upload (no bytes through this API)","description":"Returns a signed multipart POST the browser submits straight to object storage, so the file never transits the web app or the gateway. This is the ONLY workable path for video from a browser: serverless hosts cap request bodies at ~4.5MB. Validation happens BEFORE signing (same content-type allowlist and per-kind size caps as POST /uploads) and the limits are then baked into the signature itself — the policy carries a content-length-range and an exact Content-Type condition, so storage rejects a client that uploads something other than what it declared. The per-user hourly rate limit is consumed HERE, since signing is the step we control. The signature is short-lived (default 5 minutes). Submit every entry of `fields` as form fields FIRST and the file LAST, then call POST /uploads/complete with the returned `key`. STORE-DEPENDENT: on an S3-compatible target the size and content-type conditions are inside the signed policy and the bucket needs CORS allowing POST from your origin; on Cloudinary the signature pins the object id only (its API cannot carry a size condition) and no CORS setup is needed. Either way POST /uploads/complete re-reads the stored object and DISCARDS anything outside the caps, so an oversized upload never becomes attachable.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contentType","sizeBytes"],"properties":{"contentType":{"type":"string","example":"video/mp4"},"sizeBytes":{"type":"integer","minimum":1,"example":7864320}}}}}},"responses":{"201":{"description":"The signed upload","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_PresignedUpload"}}}}}},"400":{"description":"Unsupported type / declared size over the cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"Media storage unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/uploads/complete":{"post":{"summary":"Verify a direct upload and get the URL to attach","description":"Call after the browser has POSTed the file to storage. Verifies the object exists, that its stored size and content type are within the same limits, and THAT THE KEY BELONGS TO THE CALLER — keys are uploads/<userId>/..., so without that check one user could complete, and thereby claim, another user's object. An object that fails verification is deleted rather than left attachable. Returns the same shape as POST /uploads.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["key"],"properties":{"key":{"type":"string"}}}}}},"responses":{"201":{"description":"The verified media","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_UploadResult"}}}}}},"400":{"description":"Stored object failed verification (discarded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN — the key does not belong to you","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Nothing was uploaded at that key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"Media storage unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/topics":{"get":{"summary":"The shared topic vocabulary (the Explore chooser's chips)","description":"ONE flat vocabulary used by BOTH users and content: the keys returned here are the keys a viewer saves as interests AND the keys posts/streams/store items are tagged with. That symmetry is what makes \"pick what you want to watch\" filter anything — a per-surface enum would need a translation table that drifts. Public, because the picker renders before sign-in. Operator-managed (see POST /admin/topics): the set grows without a deploy, but users pick from it and never create. Pass `surface` to get only the chips ONE screen draws, in THAT screen order: `home` is Home topic row (tech, shows, crypto, science, real-estate, music, relationships, gaming) and `composer` is the gist-room composer eleven. A surface never renames or re-keys anything, it only chooses and orders, so a key means the same thing everywhere. Omit it for the full vocabulary, which is what interests and ?topics= validation use. An unknown surface is a 400.","tags":["market-square"],"parameters":[{"name":"surface","in":"query","required":false,"schema":{"type":"string","enum":["home","composer"]},"description":"Only this screen chips, in this screen order. Each returned sortOrder is the position ON THAT SURFACE, so sorting by it preserves the design order. Omit for every topic."}],"responses":{"200":{"description":"The vocabulary, in display order","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Topic"}}}}}}},"400":{"description":"VALIDATION_ERROR: `surface` is not a known surface","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/interests":{"get":{"summary":"The viewer's chosen topics","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"The selection","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"topics":{"type":"array","items":{"type":"string"}}}}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"put":{"summary":"Replace the viewer's chosen topics","description":"Wholesale replace, not merge. An EMPTY array is valid and means \"no preference\" — it is not the same as never having chosen. Unknown keys are REJECTED by name (400) rather than silently dropped, because a picker that quietly discards a chip looks saved when it is not.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["topics"],"properties":{"topics":{"type":"array","items":{"type":"string"},"maxItems":50}}}}}},"responses":{"200":{"description":"The saved selection","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"topics":{"type":"array","items":{"type":"string"}}}}}}}}},"400":{"description":"VALIDATION_ERROR — unknown topic key(s), named in the message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/topics":{"post":{"summary":"ADMIN: add a topic to the vocabulary","description":"The vocabulary is data, not a code enum, so it grows without a deploy — but only operators write to it. A duplicate key is a 409, never a silent overwrite.","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["key","label"],"properties":{"key":{"type":"string","description":"Lowercase slug; stable forever."},"label":{"type":"string","description":"Display string."},"sortOrder":{"type":"integer","default":100}}}}}},"responses":{"201":{"description":"The topic","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Topic"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"CONFLICT — that key already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/topics/{key}":{"patch":{"summary":"ADMIN: rename or reorder a topic","description":"The KEY is immutable — content and saved interests reference it. Only the display label and ordering are patchable.","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string"},"sortOrder":{"type":"integer"}}}}}},"responses":{"200":{"description":"The topic","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Topic"}}}}}},"400":{"description":"VALIDATION_ERROR — at least one field is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"FORBIDDEN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Topic not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/spotlight":{"get":{"summary":"Weekly spotlight leaderboard (worker-materialized)","description":"Profiles carry `isFollowing` for authenticated callers so the rail Follow button can render its state; omitted when anonymous.","security":[{},{"market-square_bearerAuth":[]}],"tags":["market-square"],"parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["weekly"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":20}}],"responses":{"200":{"description":"Leaderboard","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"profile":{"$ref":"#/components/schemas/market-square_PublicProfile"},"score":{"type":"string"},"rank":{"type":"integer"}}}},"computedAt":{"type":"string","nullable":true}}}}}}}}}}},"/v1/market-square/verification/rule":{"get":{"summary":"Verification single-rule (thresholds are `proposed` until PRD §10 resolves)","tags":["market-square"],"responses":{"200":{"description":"The rule","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_VerificationRule"}}}}}}}}},"/v1/market-square/verification/requests":{"post":{"summary":"Request verification (approval is admin-actioned, never automatic)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["earned","paid"]}}}}}},"responses":{"201":{"description":"The request","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_VerificationRequest"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Already verified or already pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/verification":{"get":{"summary":"Own verification state + latest request","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"The owner's verification + billing view","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_MyVerification"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/creator-application":{"post":{"summary":"Apply for the creator role (one pending application per user)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":500,"description":"Optional pitch — \"what will you stream?\""}}}}}},"responses":{"201":{"description":"The application","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_RoleApplication"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Already creator+ or an application is already pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}},"get":{"summary":"The caller's latest creator application (null when never applied)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"Latest application or null","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"allOf":[{"$ref":"#/components/schemas/market-square_RoleApplication"}],"nullable":true}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/role-applications":{"get":{"summary":"ADMIN: role applications for review (default status=pending)","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Application page","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_RoleApplication"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/role-applications/{id}/resolve":{"post":{"summary":"ADMIN: approve/reject a creator application (approve sets profile.role='creator' and emits market-square.profile.role-changed)","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["approve"],"properties":{"approve":{"type":"boolean"},"note":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"The resolved application","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_RoleApplication"}}}}}},"400":{"description":"Application already resolved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Application not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/stats":{"get":{"summary":"ADMIN: console landing figures (only what this service owns)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]},{"market-square_adminKey":[]}],"responses":{"200":{"description":"Counts","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"activePosts":{"type":"integer"},"liveStreams":{"type":"integer"},"publishedStoreItems":{"type":"integer"},"creators":{"type":"integer"},"admins":{"type":"integer"},"pendingRoleApplications":{"type":"integer"},"pendingVerificationRequests":{"type":"integer"},"openReports":{"type":"integer"}}}}}}}},"401":{"description":"No credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not an administrator / wrong key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/verification-requests":{"get":{"summary":"ADMIN: verification review queue (applicant hydrated)","tags":["market-square"],"security":[{"market-square_bearerAuth":[]},{"market-square_adminKey":[]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","approved","rejected"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Queue","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_VerificationRequest"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"401":{"description":"No credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not an administrator","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/reports":{"get":{"summary":"ADMIN: moderation queue with the REPORTED CONTENT hydrated","description":"Each row carries the hydrated `reporter` and `target` (the post/comment/stream message/profile that was reported), because a moderator cannot judge a report without seeing what it points at.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]},{"market-square_adminKey":[]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["open","actioned","dismissed"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Queue","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Report"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"401":{"description":"No credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not an administrator","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/profiles":{"get":{"summary":"ADMIN: people table with free-text and facet filters","tags":["market-square"],"security":[{"market-square_bearerAuth":[]},{"market-square_adminKey":[]}],"parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"username, display name or id"},{"name":"role","in":"query","schema":{"type":"string","enum":["citizen","creator","ambassador","worldstreet"]}},{"name":"verification","in":"query","schema":{"type":"string","enum":["none","pending","verified","lapsed"]}},{"name":"orgBadge","in":"query","schema":{"type":"string","enum":["market","ark"]}},{"name":"isAdmin","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"People","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Profile"}},"nextCursor":{"type":"string","nullable":true}}}}}}}},"401":{"description":"No credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Not an administrator","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/profiles/{id}/admin":{"post":{"summary":"BOOTSTRAP: grant or revoke the operator flag","description":"INTERNAL KEY ONLY — deliberately no user-token path, so a compromised admin session cannot mint further admins; that requires the deployment secret. Also settable at boot via MARKET_SQUARE_BOOTSTRAP_ADMIN_DID, which applies ONLY while no admin exists.","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["isAdmin"],"properties":{"isAdmin":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated profile","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Profile"}}}}}},"401":{"description":"Admin key not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Requires the internal admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/store/items":{"post":{"summary":"ADMIN: create a store item","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_AdminCreateStoreItemRequest"}}}},"responses":{"201":{"description":"The item","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StoreItem"}}}}}},"401":{"description":"Admin key not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/store/items/{id}":{"patch":{"summary":"ADMIN: update a store item (publish/archive)","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The item","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_StoreItem"}}}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/verification/{requestId}/resolve":{"post":{"summary":"ADMIN: approve/reject a verification request (updates profile.verification)","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["approve"],"properties":{"approve":{"type":"boolean"},"note":{"type":"string"}}}}}},"responses":{"200":{"description":"The resolved request","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_VerificationRequest"}}}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/reports/{id}/resolve":{"post":{"summary":"ADMIN: resolve a report (remove soft-deletes the target content)","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["remove","dismiss"]}}}}}},"responses":{"200":{"description":"The resolved report","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Report"}}}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Report not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/me/verification/renew":{"post":{"summary":"Renew verification for another period (KASH)","description":"The platform GRANTS verification — this only keeps an already-granted badge alive. Month one is free; afterwards it costs VERIFICATION_PRICE_KASH per period. Coverage extends from max(now, paidThrough), so renewing early loses no days, and a `lapsed` badge is restored immediately with NO re-approval. Debits through the PaymentRail with the coverage window as the idempotency key and writes an immutable kash_ledger row. NOTE: PAYMENT_RAIL currently defaults to `mock` until the kash team ships /rail/* (docs/handoffs/market-square-kash-rail.md) — the flow is built against the port, real value movement waits on them.","tags":["market-square"],"security":[{"market-square_bearerAuth":[]}],"responses":{"200":{"description":"Updated verification state","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_MyVerification"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"402":{"description":"PAYMENT_FAILED — rail declined; verification state unchanged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"409":{"description":"Verification has not been granted to this profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"429":{"description":"RATE_LIMITED (TOO_MANY_REQUESTS) — per-user write budget spent. error.details = { action, limit, windowSeconds, retryAfterSeconds }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"502":{"description":"PROVIDER_ERROR — rail unreachable; state unchanged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/profiles/{id}/verification":{"post":{"summary":"ADMIN: grant or revoke verification (platform-initiated)","description":"The TikTok model — we pick who gets verified; the user need not have applied. Granting stamps verifiedSince (once) and opens the free trial window. `verified: false` revokes entirely (distinct from lapsing).","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["verified"],"properties":{"verified":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated profile","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Profile"}}}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/profiles/{id}/org-badge":{"post":{"summary":"ADMIN: set or clear a profile org badge (MARKET / ARK)","description":"Operator-only. Who qualifies is a product decision: the badge is never derived from role and never self-assignable. Pass null to clear.","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["badge"],"properties":{"badge":{"type":"string","enum":["market","ark"],"nullable":true}}}}}},"responses":{"200":{"description":"The updated profile","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Profile"}}}}}},"400":{"description":"VALIDATION_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/market-square/admin/streams":{"post":{"summary":"ADMIN: create a WorldStreet-owned (house) stream","tags":["market-square"],"security":[{"market-square_adminKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_CreateStreamRequest"}}}},"responses":{"201":{"description":"The stream","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market-square_Stream"}}}}}},"403":{"description":"Invalid admin key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/market-square_ErrorResponse"}}}}}}},"/v1/user-management/users/{id}/activity":{"get":{"summary":"Paginated on-chain activity across the authenticated user’s linked wallets","description":"Requires a Privy access JWT whose subject exactly matches id. Base and Solana mainnet by default; EVM coverage is configured with ACTIVITY_EVM_CHAINS. Wallet mappings are cached for 60 seconds and activity pages for 30 seconds. Cursors expire after 15 minutes and are scoped to the user. Provider failures return an error, never a misleading empty history.","security":[{"user-management_PrivyAccessToken":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"success: true; data: { items: [{ id, hash, chain, wallet, timestamp (Unix seconds), status, details }], nextCursor, generatedAt, chains }. Items are newest first and deduplicated by chain and transaction hash; details contain provider transaction data."},"400":{"description":"Invalid limit or cursor, expired cursor, or changed linked wallets"},"401":{"description":"Missing, invalid, or expired Privy access JWT"},"403":{"description":"JWT subject does not match the requested user"},"502":{"description":"Transaction provider unavailable or returned invalid data"},"503":{"description":"Provider not configured or wallet network unsupported"}},"tags":["user-management"]}},"/v1/user-management/health":{"get":{"summary":"Service health","responses":{"200":{"description":"Healthy"}},"tags":["user-management"]}},"/v1/user-management/docs":{"get":{"summary":"Interactive Swagger UI","responses":{"200":{"description":"HTML UI"}},"tags":["user-management"]}},"/v1/user-management/admin/users":{"get":{"summary":"List a cursor-paginated page of Privy users","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Privy user page"}},"tags":["user-management"]}},"/v1/user-management/admin/users/stats":{"get":{"summary":"Count Privy users by contact and sign-in capability","description":"Returns a cached snapshot refreshed from all Privy users in the background. Categories overlap: one user can be counted in email, wallet, and social sign-in totals.","security":[{"user-management_AdminApiKey":[]}],"responses":{"200":{"description":"Current user counts","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","required":["totalUsers","reachableByEmail","withWallet","withSocialSignIn"],"properties":{"totalUsers":{"type":"integer","minimum":0},"reachableByEmail":{"type":"integer","minimum":0},"withWallet":{"type":"integer","minimum":0},"withSocialSignIn":{"type":"integer","minimum":0}}}}}}}}},"tags":["user-management"]}},"/v1/user-management/admin/users/{id}":{"get":{"summary":"Get one Privy user","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privy user"}},"tags":["user-management"]},"delete":{"summary":"Permanently delete one Privy user","security":[{"user-management_AdminApiKey":[]}],"description":"Requires x-confirm-user-deletion to exactly equal the path user ID.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"x-confirm-user-deletion","in":"header","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"}},"tags":["user-management"]}},"/v1/user-management/admin/users/{id}/email":{"post":{"summary":"Send an email to one Privy user","security":[{"user-management_AdminApiKey":[]}],"description":"Uses the first linked Privy email and submits through the configured email provider.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subject","html"],"properties":{"subject":{"type":"string"},"html":{"type":"string"},"text":{"type":"string"},"senderId":{"type":"string","format":"uuid","description":"Approved sender profile. Omit to use the configured default."},"sender":{"type":"object","description":"Inline sender details. Use instead of senderId; the domain must be approved.","required":["email","name"],"properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","maxLength":100},"replyTo":{"type":"string","format":"email"}}}}}}}},"responses":{"202":{"description":"Accepted by the configured email provider"}},"tags":["user-management"]}},"/v1/user-management/admin/email-senders":{"get":{"summary":"List approved email sender profiles","security":[{"user-management_AdminApiKey":[]}],"responses":{"200":{"description":"Approved senders, default first"}},"tags":["user-management"]},"post":{"summary":"Add an approved email sender profile","description":"The email domain must be included in EMAIL_ALLOWED_SENDER_DOMAINS and authenticated with the configured provider.","security":[{"user-management_AdminApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["email","name"],"properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","maxLength":100},"replyTo":{"type":"string","format":"email"}}}}}},"responses":{"201":{"description":"Sender added"},"400":{"description":"Invalid input or unapproved domain"},"409":{"description":"Sender email already exists"}},"tags":["user-management"]}},"/v1/user-management/admin/email-senders/{id}":{"delete":{"summary":"Remove a non-default sender profile","description":"Existing campaigns retain their sender snapshot. The configured default sender cannot be removed.","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Sender removed"},"404":{"description":"Sender not found"},"409":{"description":"Default sender cannot be removed"}},"tags":["user-management"]}},"/v1/user-management/admin/campaigns":{"get":{"summary":"List campaigns","security":[{"user-management_AdminApiKey":[]}],"responses":{"200":{"description":"Campaigns"}},"tags":["user-management"]},"post":{"summary":"Create a draft campaign","security":[{"user-management_AdminApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","subject","html"],"properties":{"name":{"type":"string"},"subject":{"type":"string"},"html":{"type":"string"},"text":{"type":"string"},"senderId":{"type":"string","format":"uuid","description":"Approved sender profile. Omit to use the configured default."},"sender":{"type":"object","description":"Inline sender details. Use instead of senderId; the domain must be approved.","required":["email","name"],"properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","maxLength":100},"replyTo":{"type":"string","format":"email"}}}}}}}},"responses":{"201":{"description":"Draft created"}},"tags":["user-management"]}},"/v1/user-management/admin/campaigns/{id}":{"get":{"summary":"Get one campaign","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Campaign"},"404":{"description":"Campaign not found"}},"tags":["user-management"]},"delete":{"summary":"Delete a draft campaign","description":"Permanently deletes a campaign only while its status is draft. Campaigns in every other status are retained for audit history.","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Draft deleted"},"404":{"description":"Campaign not found"},"409":{"description":"Campaign is no longer a draft"}},"tags":["user-management"]}},"/v1/user-management/admin/campaigns/{id}/send":{"post":{"summary":"Queue a campaign for all unique Privy email users","security":[{"user-management_AdminApiKey":[]}],"description":"Requires an explicit audience. Use audience=selected with 1-1000 Privy user IDs, or audience=all without userIds. Provider suppressions are honored.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","oneOf":[{"type":"object","additionalProperties":false,"required":["confirm","audience","userIds"],"properties":{"confirm":{"type":"boolean","const":true},"audience":{"type":"string","const":"selected"},"userIds":{"type":"array","minItems":1,"maxItems":1000,"uniqueItems":true,"items":{"type":"string","pattern":"^did:privy:"}}}},{"type":"object","additionalProperties":false,"required":["confirm","audience"],"properties":{"confirm":{"type":"boolean","const":true},"audience":{"type":"string","const":"all"}}}]}}}},"responses":{"202":{"description":"Campaign queued for asynchronous processing"}},"tags":["user-management"]}},"/v1/user-management/admin/campaigns/{id}/recipients":{"get":{"summary":"List and filter the durable recipient ledger","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","submitting","accepted","processed","delivered","deferred","bounced","dropped","api_failed","skipped"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Recipient ledger page"}},"tags":["user-management"]}},"/v1/user-management/admin/campaigns/{id}/retry":{"post":{"summary":"Safely retry recipients not accepted by the email provider","description":"Only pending and api_failed are allowed. Accepted, processed, delivered, deferred, bounced, and dropped recipients cannot be resent by this endpoint.","security":[{"user-management_AdminApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["confirm","statuses"],"properties":{"confirm":{"type":"boolean","const":true},"statuses":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"string","enum":["pending","api_failed"]}}}}}}},"responses":{"202":{"description":"Matching recipients queued"},"409":{"description":"Unsafe legacy campaign, wrong state, or no matching recipients"}},"tags":["user-management"]}},"/v1/user-management/webhooks/sendgrid/events":{"post":{"summary":"Signed SendGrid Event Webhook receiver","description":"Public endpoint authenticated with SendGrid ECDSA signature headers.","responses":{"200":{"description":"Events recorded or already deduplicated"},"401":{"description":"Invalid signature or stale timestamp"},"503":{"description":"Webhook public key is not configured"}},"tags":["user-management"]}},"/v1/user-management/webhooks/mailgun/events":{"post":{"summary":"Signed Mailgun Event Webhook receiver","description":"Public endpoint authenticated with the Mailgun HMAC-SHA256 signature embedded in its raw JSON body.","responses":{"200":{"description":"Event recorded or already deduplicated"},"401":{"description":"Invalid signature, body, or stale timestamp"},"503":{"description":"Webhook signing key is not configured"}},"tags":["user-management"]}},"/v1/user-management/admin/queues/":{"get":{"summary":"Read-only Bull Board for campaign and dead-letter queues","description":"Browser UI protected by separate HTTP Basic credentials. Campaign-level execution only; use the recipient ledger for delivery status.","security":[{"user-management_basicAuth":[]}],"responses":{"200":{"description":"Bull Board HTML"},"401":{"description":"Basic authentication required"}},"tags":["user-management"]}}},"components":{"schemas":{"HealthResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","example":"api"},"uptimeSeconds":{"type":"integer"}}}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"code":{"type":"string","example":"NOT_FOUND"},"message":{"type":"string"},"details":{}}}}},"rwa_Asset":{"type":"object","required":["id","chain","address","symbol","name","issuer","category","freelyTradable"],"properties":{"id":{"type":"string","example":"ethereum:0x96F6eF951840721AdBF46Ac996b59E0235CB985C"},"chain":{"type":"string","enum":["solana","ethereum","base","arbitrum","bsc","polygon"]},"address":{"type":"string"},"symbol":{"type":"string","example":"USDY"},"name":{"type":"string","example":"Ondo US Dollar Yield"},"issuer":{"type":"string","example":"Ondo Finance"},"category":{"type":"string","example":"treasury"},"yieldApyBps":{"type":"integer","example":355},"priceUsd":{"type":"string","nullable":true,"description":"Decimal string; best-effort — null when the upstream price source is cold"},"freelyTradable":{"type":"boolean"},"accessMode":{"type":"string","enum":["dex","issuer","hybrid"]},"kycRequired":{"type":"boolean"},"minInvestmentUsd":{"type":"string","nullable":true},"transferRestrictions":{"type":"string"},"redemption":{"type":"string"},"issuerUrl":{"type":"string"},"attestationUrl":{"type":"string"},"deprecated":{"type":"boolean"},"tvlUsd":{"type":"string"}}},"rwa_Category":{"type":"object","properties":{"category":{"type":"string"},"count":{"type":"integer"}}},"rwa_YieldHistoryPoint":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time"},"tvlUsd":{"type":"number","nullable":true},"apy":{"type":"number","nullable":true},"apyBase":{"type":"number","nullable":true},"apyReward":{"type":"number","nullable":true}}},"rwa_QuoteRequest":{"type":"object","required":["chain","inputToken","outputToken","amountIn"],"properties":{"chain":{"type":"string","enum":["solana","ethereum","base","arbitrum","bsc","polygon"]},"inputToken":{"type":"string","description":"EVM 0x address / Solana mint; native sentinel supported"},"outputToken":{"type":"string"},"amountIn":{"type":"string","pattern":"^\\d+$","description":"BASE units, decimal string — never a number, never human decimals"},"slippageBps":{"type":"integer","minimum":1,"maximum":5000,"default":50}}},"rwa_BuildRequest":{"allOf":[{"$ref":"#/components/schemas/rwa_QuoteRequest"},{"type":"object","required":["taker"],"properties":{"taker":{"type":"string","description":"The USER's wallet address — signs client-side"},"provider":{"type":"string","description":"Pin a specific routing provider"},"simulate":{"type":"boolean","default":true,"description":"Escape hatch for upstream RPC incidents: false skips the venue-side simulation gate — steps return UNVERIFIED (warnings[] flags it) and the client must simulate before broadcasting."}}}]},"rwa_Quote":{"type":"object","properties":{"provider":{"type":"string","example":"jupiter"},"input":{"type":"object"},"output":{"type":"object"},"priceImpactBps":{"type":"integer","nullable":true},"route":{"type":"array","items":{"type":"object"}}}},"rwa_Action":{"type":"object","properties":{"actionId":{"type":"string"},"chain":{"type":"string","enum":["solana","ethereum","base","arbitrum","bsc","polygon"]},"expiresAt":{"type":"string","format":"date-time"},"steps":{"type":"array","items":{"type":"object"},"description":"Ordered steps for the client wallet: sign-transaction | sign-typed-data | post-to-endpoint (upstream steps[] contract, passed through verbatim)"},"quote":{"type":"object"},"warnings":{"type":"array","items":{"type":"string"}},"platformFee":{"$ref":"#/components/schemas/rwa_PlatformFee"}}},"rwa_PlatformFee":{"type":"object","description":"Platform fee the client MUST collect: transfer `amount` of `token` to `account` alongside executing steps. The steps price the NET (amountIn − amount) swap. Absent when the fee is 0.","properties":{"bps":{"type":"integer","example":50},"account":{"type":"string","example":"0x7666EBd78810f0024f930928A5fa779263C8d67E"},"token":{"type":"string","description":"Input-token address the fee is denominated in"},"amount":{"type":"string","description":"Base units (decimal string)"}}},"rwa_HealthResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","example":"rwa"},"uptimeSeconds":{"type":"integer"}}}}},"rwa_AssetListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/rwa_Asset"}}}},"rwa_AssetResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/rwa_Asset"}}},"rwa_CategoryListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/rwa_Category"}}}},"rwa_YieldHistoryResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/rwa_YieldHistoryPoint"}}}},"rwa_QuoteResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"best":{"$ref":"#/components/schemas/rwa_Quote"},"all":{"type":"array","items":{"$ref":"#/components/schemas/rwa_Quote"}},"failed":{"type":"array","items":{"type":"object"}}}}}},"rwa_ActionResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/rwa_Action"}}},"rwa_ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"code":{"type":"string","description":"VALIDATION_ERROR | ASSET_NOT_TRADABLE | NOT_FOUND | NO_ROUTE | INSUFFICIENT_LIQUIDITY | SIMULATION_FAILED | QUOTE_EXPIRED | SERVICE_UNAVAILABLE"},"message":{"type":"string"},"details":{}}}}},"trade_ErrorEnvelope":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string"}}}}},"world-street-vault_TokenAmount":{"type":"object","properties":{"amount":{"type":"string","description":"Human-readable token amount (formatted from wei)"},"tokenSymbol":{"type":"string","example":"ETH"},"usdValue":{"type":"number"},"formattedUsd":{"type":"string","example":"$12.34"}}},"world-street-vault_Game":{"type":"object","properties":{"gameId":{"type":"integer"},"starter":{"type":"string","nullable":true},"king":{"type":"string","nullable":true},"pot":{"$ref":"#/components/schemas/world-street-vault_TokenAmount"},"minWager":{"$ref":"#/components/schemas/world-street-vault_TokenAmount"},"endTime":{"type":"integer","description":"Unix seconds"},"timeRemaining":{"type":"integer"},"settled":{"type":"boolean"},"active":{"type":"boolean"}}},"world-street-vault_GamesResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"games":{"type":"array","items":{"$ref":"#/components/schemas/world-street-vault_Game"}},"nextCursor":{"type":"string","nullable":true,"description":"Pass back as ?cursor= for the next page; null at the end."}}}}},"world-street-vault_ConfigResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"contract":{"type":"string"},"implementation":{"type":"string","nullable":true},"owner":{"type":"string"},"treasury":{"type":"string"},"minStartStakeWei":{"type":"string"},"timerSeconds":{"type":"integer"},"winnerBps":{"type":"integer","example":5000},"starterBps":{"type":"integer","example":1000},"treasuryBps":{"type":"integer","example":4000},"paused":{"type":"boolean"}}}}},"world-street-vault_GameResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"game":{"$ref":"#/components/schemas/world-street-vault_Game"}}}}},"perp_JoinWaitlistRequest":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","maxLength":320,"example":"trader@example.com","description":"Normalized server-side (trimmed, lowercased)."},"source":{"type":"string","maxLength":64,"example":"launch-landing-page","description":"Optional marketing-attribution tag (campaign, page, referrer)."}}},"perp_WaitlistEntry":{"type":"object","properties":{"email":{"type":"string","example":"trader@example.com"},"source":{"type":"string","example":"launch-landing-page"},"createdAt":{"type":"string","format":"date-time"}}},"perp_WaitlistListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/perp_WaitlistEntry"}},"total":{"type":"integer","description":"Total signups on the list."},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}},"perp_WaitlistDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"email":{"type":"string"},"deleted":{"type":"boolean","enum":[true]}}}}},"perp_WaitlistJoinResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"email":{"type":"string","description":"The normalized email that was recorded."},"alreadyJoined":{"type":"boolean","description":"True when the email was already on the list (200 instead of 201)."}}}}},"perp_ArkWallet":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"address":{"type":"string"},"isActive":{"type":"boolean"},"smartAccountUpgradedAt":{"type":"string","format":"date-time","nullable":true},"dextopusDepositAddress":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"perp_WalletResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/perp_ArkWallet"}}},"perp_ArkAsset":{"type":"object","properties":{"id":{"type":"string"},"assetIndex":{"type":"integer"},"dex":{"type":"string","example":""},"symbol":{"type":"string","example":"BTC"},"category":{"type":"string","nullable":true,"example":"crypto"},"szDecimals":{"type":"integer"},"maxLeverage":{"type":"integer"},"isActive":{"type":"boolean"}}},"perp_AssetListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_ArkAsset"}}}},"perp_AssetContext":{"type":"object","properties":{"symbol":{"type":"string","example":"BTC"},"markPrice":{"type":"string"},"oraclePrice":{"type":"string"},"prevDayPrice":{"type":"string","description":"24h change basis: (markPrice - prevDayPrice) / prevDayPrice."},"dayVolumeUsd":{"type":"string"},"openInterest":{"type":"string","description":"Base asset units, not USD."},"fundingRate":{"type":"string"}}},"perp_MarketContextListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_AssetContext"}}}},"perp_FundingHistoryEntry":{"type":"object","properties":{"coin":{"type":"string"},"fundingRate":{"type":"string"},"premium":{"type":"string"},"time":{"type":"integer","description":"Unix ms."}}},"perp_Candle":{"type":"object","properties":{"t":{"type":"integer","description":"Open time, unix ms."},"T":{"type":"integer","description":"Close time, unix ms."},"s":{"type":"string"},"i":{"type":"string"},"o":{"type":"string"},"c":{"type":"string"},"h":{"type":"string"},"l":{"type":"string"},"v":{"type":"string","description":"Volume in the base asset, not USD."},"n":{"type":"integer"}}},"perp_CandlesResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_Candle"}}}},"perp_FundingHistoryResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_FundingHistoryEntry"}}}},"perp_ArkPricesResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","additionalProperties":{"type":"string"},"example":{"BTC":"65000.5","ETH":"3200.1"}}}},"perp_AccountStateResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","description":"Live margin summary, withdrawable balance, and open positions, passed through unmodified.","properties":{"withdrawable":{"type":"string"},"marginSummary":{"type":"object"},"crossMarginSummary":{"type":"object"},"assetPositions":{"type":"array","items":{"type":"object"}}}}}},"perp_ArbitrumBalanceResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"balance":{"type":"string","example":"12.345678"}}}}},"perp_ArkPositionView":{"type":"object","properties":{"id":{"type":"string"},"walletId":{"type":"string"},"assetId":{"type":"string"},"side":{"type":"string","enum":["long","short"]},"size":{"type":"string"},"entryPrice":{"type":"string"},"leverage":{"type":"integer"},"marginMode":{"type":"string","enum":["isolated","cross"]},"status":{"type":"string","enum":["open","closed"]},"markPrice":{"type":"string","nullable":true},"unrealizedPnlUsdc":{"type":"string","nullable":true},"accruedFundingUsdc":{"type":"string","description":"Not yet computed — always \"0\" for now."},"openedAt":{"type":"string","format":"date-time"}}},"perp_ArkPositionListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_ArkPositionView"}}}},"perp_ArkClosedPositionView":{"type":"object","properties":{"id":{"type":"string"},"walletId":{"type":"string"},"assetId":{"type":"string"},"symbol":{"type":"string","example":"BTC"},"side":{"type":"string","enum":["long","short"]},"size":{"type":"string"},"entryPrice":{"type":"string"},"leverage":{"type":"integer"},"marginMode":{"type":"string","enum":["isolated","cross"]},"status":{"type":"string","enum":["closed"]},"closeReason":{"type":"string","enum":["take_profit","stop_loss","manual_close","liquidation","reconciled"]},"closePrice":{"type":"string"},"realizedPnlUsdc":{"type":"string"},"openedAt":{"type":"string","format":"date-time"},"closedAt":{"type":"string","format":"date-time"}}},"perp_ArkClosedPositionListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_ArkClosedPositionView"}}}},"perp_ArkOrderRow":{"type":"object","properties":{"id":{"type":"string"},"walletId":{"type":"string"},"assetId":{"type":"string"},"cloid":{"type":"string"},"externalOrderId":{"type":"string","nullable":true},"parentOrderId":{"type":"string","nullable":true},"orderType":{"type":"string","enum":["market","limit","take_profit","stop_loss"]},"side":{"type":"string","enum":["buy","sell"]},"size":{"type":"string"},"limitPrice":{"type":"string","nullable":true},"reduceOnly":{"type":"boolean"},"status":{"type":"string","enum":["submitted","open","partially_filled","filled","cancelled","rejected"]}}},"perp_ArkOrderListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/perp_ArkOrderRow"}}}},"perp_ArkSignature":{"type":"object","description":"An ECDSA signature {r, s, v} produced CLIENT-SIDE by the wallet's own embedded key.","required":["r","s","v"],"properties":{"r":{"type":"string"},"s":{"type":"string"},"v":{"type":"number"}}},"perp_PlaceOrderRequest":{"type":"object","required":["walletId","assetSymbol","side","size"],"properties":{"walletId":{"type":"string"},"assetSymbol":{"type":"string","example":"ETH"},"side":{"type":"string","enum":["buy","sell"]},"size":{"type":"string","description":"Decimal string, base units","example":"1.5"},"limitPrice":{"type":"string","description":"Omit for a market order"},"takeProfitPrice":{"type":"string"},"stopLossPrice":{"type":"string"},"slippagePct":{"type":"number","maximum":0.2,"description":"Market-order slippage tolerance"}}},"perp_PreparedOrder":{"type":"object","description":"The unsigned action wire format plus the cloids the client must sign and echo back unchanged.","properties":{"action":{"type":"object","description":"Signed action (type: \"order\"), canonicalized key order."},"nonce":{"type":"integer"},"entryCloid":{"type":"string"},"takeProfitCloid":{"type":"string","nullable":true},"stopLossCloid":{"type":"string","nullable":true}}},"perp_PreparedOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/perp_PreparedOrder"}}},"perp_SubmitOrderRequest":{"type":"object","required":["walletId","prepared","signature"],"properties":{"walletId":{"type":"string"},"prepared":{"allOf":[{"$ref":"#/components/schemas/perp_PreparedOrder"}],"description":"Echoed back verbatim from /ark/orders/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_ArkOrder":{"type":"object","description":"One leg of the placed order (entry, take-profit, or stop-loss).","properties":{"id":{"type":"string"},"externalOrderId":{"type":"string","nullable":true,"description":"Order id, once accepted"},"orderType":{"type":"string","enum":["market","limit","take_profit","stop_loss","close"]},"status":{"type":"string","enum":["submitted","open","partially_filled","filled","cancelled","rejected"]}}},"perp_ArkOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/perp_ArkOrder"}}},"perp_PlaceOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"entryOrder":{"$ref":"#/components/schemas/perp_ArkOrder"},"takeProfitOrder":{"allOf":[{"$ref":"#/components/schemas/perp_ArkOrder"}],"nullable":true},"stopLossOrder":{"allOf":[{"$ref":"#/components/schemas/perp_ArkOrder"}],"nullable":true}}}}},"perp_PrepareLeverageRequest":{"type":"object","required":["walletId","assetSymbol","leverage","marginMode"],"properties":{"walletId":{"type":"string"},"assetSymbol":{"type":"string","example":"ETH"},"leverage":{"type":"integer","minimum":1,"maximum":200},"marginMode":{"type":"string","enum":["isolated","cross"]}}},"perp_PreparedLeverageResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","description":"{ action, nonce } to sign, or { alreadySet: true } if the setting is already what was requested.","properties":{"action":{"type":"object","description":"Signed action (type: \"updateLeverage\")."},"nonce":{"type":"integer"},"alreadySet":{"type":"boolean"}}}}},"perp_SubmitLeverageRequest":{"type":"object","required":["walletId","action","nonce","signature"],"properties":{"walletId":{"type":"string"},"action":{"type":"object","description":"Echoed back verbatim from /ark/leverage/prepare."},"nonce":{"type":"integer"},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_UpdatedResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"updated":{"type":"boolean","enum":[true]}}}}},"perp_PrepareCancelOrderRequest":{"type":"object","required":["walletId","orderId"],"properties":{"walletId":{"type":"string"},"orderId":{"type":"string","description":"Our own order id, not the externalOrderId."}}},"perp_PreparedCancel":{"type":"object","properties":{"action":{"type":"object","description":"Signed action (type: \"cancel\")."},"nonce":{"type":"integer"},"orderId":{"type":"string"}}},"perp_PreparedCancelResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/perp_PreparedCancel"}}},"perp_SubmitCancelOrderRequest":{"type":"object","required":["walletId","prepared","signature"],"properties":{"walletId":{"type":"string"},"prepared":{"allOf":[{"$ref":"#/components/schemas/perp_PreparedCancel"}],"description":"Echoed back verbatim from /ark/orders/cancel/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_PrepareClosePositionRequest":{"type":"object","required":["walletId","positionId"],"properties":{"walletId":{"type":"string"},"positionId":{"type":"string"},"size":{"type":"string","description":"Partial-close size, decimal string; defaults to the full position."},"slippagePct":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":0.2}}},"perp_PreparedClosePosition":{"type":"object","properties":{"action":{"type":"object","description":"Signed action (type: \"order\"), a single reduce-only IOC leg."},"nonce":{"type":"integer"},"cloid":{"type":"string"},"positionId":{"type":"string"}}},"perp_PreparedClosePositionResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/perp_PreparedClosePosition"}}},"perp_SubmitClosePositionRequest":{"type":"object","required":["walletId","prepared","signature"],"properties":{"walletId":{"type":"string"},"prepared":{"allOf":[{"$ref":"#/components/schemas/perp_PreparedClosePosition"}],"description":"Echoed back verbatim from /ark/positions/close/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_ClosePositionResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"closeOrder":{"$ref":"#/components/schemas/perp_ArkOrder"}}}}},"perp_PrepareTriggerOrderRequest":{"type":"object","required":["walletId","positionId","kind","triggerPrice"],"properties":{"walletId":{"type":"string"},"positionId":{"type":"string"},"kind":{"type":"string","enum":["take_profit","stop_loss"]},"triggerPrice":{"type":"string"}}},"perp_PreparedTriggerOrder":{"type":"object","properties":{"action":{"type":"object","description":"Signed action (type: \"order\"), a single reduce-only trigger leg."},"nonce":{"type":"integer"},"cloid":{"type":"string"},"positionId":{"type":"string"},"kind":{"type":"string","enum":["take_profit","stop_loss"]}}},"perp_PreparedTriggerOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/perp_PreparedTriggerOrder"}}},"perp_SubmitTriggerOrderRequest":{"type":"object","required":["walletId","prepared","signature"],"properties":{"walletId":{"type":"string"},"prepared":{"allOf":[{"$ref":"#/components/schemas/perp_PreparedTriggerOrder"}],"description":"Echoed back verbatim from /ark/orders/trigger/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_PrepareBridgeRequest":{"type":"object","required":["walletId"],"properties":{"walletId":{"type":"string"}}},"perp_PreparedBridgeResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","description":"Unsigned calldata for the client to send itself, bridging the wallet's entire Arbitrum USDC balance.","properties":{"to":{"type":"string","description":"The Arbitrum USDC contract address."},"data":{"type":"string","description":"ABI-encoded ERC-20 transfer calldata."},"value":{"type":"string","example":"0"},"amountUsdc":{"type":"string"}}}}},"perp_ConfirmBridgeRequest":{"type":"object","required":["walletId","txHash","amountUsdc"],"properties":{"walletId":{"type":"string"},"txHash":{"type":"string","description":"The hash of the transfer the client already broadcast."},"amountUsdc":{"type":"string","description":"Decimal string"}}},"perp_BridgeResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"treasuryMovementId":{"type":"string","description":"Track this id for settlement status."}}}}},"perp_PrepareWithdrawalRequest":{"type":"object","required":["walletId","amountUsdc"],"properties":{"walletId":{"type":"string"},"amountUsdc":{"type":"string","description":"Decimal string","example":"100"}}},"perp_PreparedWithdrawalResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"action":{"type":"object","description":"Signed action (type: \"withdraw3\")."},"nonce":{"type":"integer"}}}}},"perp_SubmitWithdrawalRequest":{"type":"object","required":["walletId","action","signature"],"properties":{"walletId":{"type":"string"},"action":{"type":"object","description":"Echoed back verbatim from /ark/withdrawals/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_WithdrawalResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"treasuryMovementId":{"type":"string","description":"Track this id for settlement status."}}}}},"perp_PendingWithdrawalResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","nullable":true,"properties":{"treasuryMovementId":{"type":"string"},"amountUsdc":{"type":"string","description":"Decimal string."},"status":{"type":"string","enum":["pending","confirmed","failed","stuck"]}}}}},"perp_BuilderFeeStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"approved":{"type":"boolean"},"maxFeeRateTenthsBps":{"type":"integer","description":"What the wallet has already granted the treasury — 0 if never approved."}}}}},"perp_PrepareBuilderFeeApprovalRequest":{"type":"object","required":["walletId"],"properties":{"walletId":{"type":"string"}}},"perp_PreparedBuilderFeeApprovalResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"action":{"type":"object","description":"Signed action (type: \"approveBuilderFee\")."},"nonce":{"type":"integer"}}}}},"perp_SubmitBuilderFeeApprovalRequest":{"type":"object","required":["walletId","action","signature"],"properties":{"walletId":{"type":"string"},"action":{"type":"object","description":"Echoed back verbatim from /ark/builder-fee/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_BuilderFeeApprovalResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"approved":{"type":"boolean","enum":[true]}}}}},"perp_AbstractionModeStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"mode":{"type":"string","enum":["disabled","unifiedAccount","portfolioMargin"]},"eligibleForBuilderFees":{"type":"boolean"}}}}},"perp_PrepareAbstractionModeRequest":{"type":"object","required":["walletId","abstraction"],"properties":{"walletId":{"type":"string"},"abstraction":{"type":"string","enum":["disabled","unifiedAccount","portfolioMargin"]}}},"perp_PreparedAbstractionModeResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"action":{"type":"object","description":"Signed action (type: \"userSetAbstraction\")."},"nonce":{"type":"integer"}}}}},"perp_SubmitAbstractionModeRequest":{"type":"object","required":["walletId","action","signature"],"properties":{"walletId":{"type":"string"},"action":{"type":"object","description":"Echoed back verbatim from /ark/abstraction-mode/prepare."},"signature":{"$ref":"#/components/schemas/perp_ArkSignature"}}},"perp_AbstractionModeChangeResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"mode":{"type":"string","enum":["disabled","unifiedAccount","portfolioMargin"]}}}}},"perp_RewardsStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"unclaimedRewards":{"type":"string","description":"Decimal string, USDC."},"claimedRewards":{"type":"string","description":"Decimal string."},"builderRewards":{"type":"string","description":"Decimal string."}}}}},"perp_HealthResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","example":"perp"},"uptimeSeconds":{"type":"integer"}}}}},"perp_ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"code":{"type":"string","description":"VALIDATION_ERROR | NOT_FOUND | CONTRACT_ERROR | SERVICE_UNAVAILABLE"},"message":{"type":"string"},"details":{}}}}},"chess_AnalysisClassification":{"type":"string","enum":["best","good","inaccuracy","mistake","blunder"]},"chess_AnalysisMotif":{"type":"string","enum":["mate","doubleCheck","discoveredCheck","fork","pin","skewer","trappedPiece","removingDefender","exploitingPin","hangingPiece","doubledPawns","isolatedPawn","openFile","openingDeviation","endgameTechnique","materialLoss","tacticalMiss","positionalDrift"]},"chess_AnalysisMoveResponse":{"type":"object","required":["ply","player","side","openingBucket","timeControl","phase","motif","classification","fen","playedUci","playedSan","coachComment","createdAt"],"properties":{"accuracyPercent":{"type":["number","null"],"format":"double","description":"Lichess-style move accuracy derived from the change in win probability."},"bestSan":{"type":["string","null"]},"bestUci":{"type":["string","null"]},"classification":{"$ref":"#/components/schemas/chess_AnalysisClassification"},"coachComment":{"type":"string","description":"Deterministic, engine-grounded coaching text for this move."},"cpAfter":{"type":["integer","null"],"format":"int32"},"cpBefore":{"type":["integer","null"],"format":"int32"},"cpLoss":{"type":["integer","null"],"format":"int32"},"createdAt":{"type":"string","format":"date-time"},"fen":{"type":"string"},"mateAfter":{"type":["integer","null"],"format":"int32"},"mateBefore":{"type":["integer","null"],"format":"int32"},"motif":{"$ref":"#/components/schemas/chess_AnalysisMotif"},"openingBucket":{"type":"string"},"phase":{"$ref":"#/components/schemas/chess_AnalysisPhase"},"playedSan":{"type":"string"},"playedUci":{"type":"string"},"player":{"type":"string"},"ply":{"type":"integer","format":"int32"},"pv":{"type":["string","null"]},"side":{"type":"string"},"timeControl":{"type":"string"}}},"chess_AnalysisPhase":{"type":"string","enum":["opening","middlegame","endgame"]},"chess_AnalysisPlayerSummaryResponse":{"type":"object","required":["side","bestMoves","goodMoves","inaccuracies","mistakes","blunders"],"properties":{"accuracyPercent":{"type":["number","null"],"format":"double"},"averageCentipawnLoss":{"type":["integer","null"],"format":"int32"},"bestMoves":{"type":"integer","format":"int32"},"blunders":{"type":"integer","format":"int32"},"goodMoves":{"type":"integer","format":"int32"},"inaccuracies":{"type":"integer","format":"int32"},"mistakes":{"type":"integer","format":"int32"},"side":{"type":"string"}}},"chess_AnalysisQueueResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_QueuedAnalysisSummaryResponse"}}}},"chess_AnalysisRequestOrigin":{"type":"string","enum":["manual","system"]},"chess_AnalysisStatus":{"type":"string","enum":["queued","running","completed","failed"]},"chess_AnalysisTier":{"type":"string","enum":["standard","premium"]},"chess_ArenaListResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_ArenaSummaryResponse"}}}},"chess_ArenaMeResponse":{"type":"object","required":["name","active","playing","rank","score"],"properties":{"active":{"type":"boolean"},"countryCode":{"type":["string","null"]},"name":{"type":"string"},"playing":{"type":"boolean"},"rank":{"type":"integer","format":"int64"},"score":{"type":"integer","format":"int32"}}},"chess_ArenaPairingResponse":{"type":"object","required":["id","white","black","status","whiteScore","blackScore","scored"],"properties":{"black":{"type":"string"},"blackScore":{"type":"integer","format":"int32"},"finishedAt":{"type":["string","null"],"format":"date-time"},"id":{"type":"string"},"matchId":{"type":["string","null"]},"scored":{"type":"boolean"},"startedAt":{"type":["string","null"],"format":"date-time"},"status":{"$ref":"#/components/schemas/chess_ArenaPairingStatus"},"white":{"type":"string"},"whiteScore":{"type":"integer","format":"int32"}}},"chess_ArenaPairingStatus":{"type":"string","enum":["creating","ongoing","white","black","draw","failed","cancelled"]},"chess_ArenaPlayerRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"walletAddress":{"type":["string","null"]}}},"chess_ArenaResponse":{"allOf":[{"$ref":"#/components/schemas/chess_ArenaSummaryResponse"},{"type":"object","required":["standings","standingOffset","standingLimit","featuredPairings"],"properties":{"featuredPairings":{"type":"array","items":{"$ref":"#/components/schemas/chess_ArenaPairingResponse"}},"me":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_ArenaMeResponse"}]},"myPairing":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_ArenaPairingResponse"}]},"standingLimit":{"type":"integer","format":"int64"},"standingOffset":{"type":"integer","format":"int64"},"standings":{"type":"array","items":{"$ref":"#/components/schemas/chess_ArenaStandingResponse"}}}}]},"chess_ArenaStandingResponse":{"type":"object","required":["rank","name","rating","score","games","wins","draws","losses","active","playing","fire"],"properties":{"active":{"type":"boolean"},"countryCode":{"type":["string","null"]},"draws":{"type":"integer","format":"int32"},"fire":{"type":"boolean"},"games":{"type":"integer","format":"int32"},"losses":{"type":"integer","format":"int32"},"name":{"type":"string"},"playing":{"type":"boolean"},"rank":{"type":"integer","format":"int64"},"rating":{"type":"integer","format":"int32"},"score":{"type":"integer","format":"int32"},"wins":{"type":"integer","format":"int32"}}},"chess_ArenaStatus":{"type":"string","enum":["created","started","finished"]},"chess_ArenaSummaryResponse":{"type":"object","required":["id","name","organizer","status","participantCount","ongoingCount","maxPlayers","timeControl","durationSeconds","startsAt"],"properties":{"durationSeconds":{"type":"integer","format":"int32"},"finishedAt":{"type":["string","null"],"format":"date-time"},"finishesAt":{"type":["string","null"],"format":"date-time"},"id":{"type":"string"},"maxPlayers":{"type":"integer","format":"int32"},"name":{"type":"string"},"ongoingCount":{"type":"integer","format":"int32"},"organizer":{"type":"string"},"participantCount":{"type":"integer","format":"int32"},"startedAt":{"type":["string","null"],"format":"date-time"},"startsAt":{"type":"string","format":"date-time"},"status":{"$ref":"#/components/schemas/chess_ArenaStatus"},"timeControl":{"$ref":"#/components/schemas/chess_TimeControl"},"winner":{"type":["string","null"]}}},"chess_BetResponse":{"type":"object","description":"A placed or resolved bet.","required":["id","matchId","bettor","outcome","stakeUsdc","status","payoutUsdc"],"properties":{"bettor":{"type":"string"},"id":{"type":"string"},"matchId":{"type":"string"},"outcome":{"type":"string"},"payoutUsdc":{"type":"string"},"stakeUsdc":{"type":"string"},"status":{"type":"string","description":"`active`, `won`, `lost`, or `refunded`."}}},"chess_CashierConfigResponse":{"type":"object","required":["chainId","tokenSymbol","tokenAddress","depositAddress","requiredConfirmations","platformFeeBps","withdrawalFeeBps","autoPayoutWinnings","rpcProvider","gasSponsored"],"properties":{"alchemyGasPolicyId":{"type":["string","null"]},"autoPayoutWinnings":{"type":"boolean","description":"Whether decisive match winnings are pushed straight to the winner's\nwallet, or left in the internal chess balance for manual withdrawal."},"chainId":{"type":"integer","format":"int64","minimum":0},"depositAddress":{"type":"string"},"gasSponsored":{"type":"boolean","description":"True when withdrawals are broadcast as EIP-7702 gas-sponsored user\noperations (the policy actually pays gas). When false the policy id is\ninformational only and the backend wallet pays its own gas."},"platformFeeBps":{"type":"integer","format":"int32","minimum":0},"requiredConfirmations":{"type":"integer","format":"int64","minimum":0},"rpcProvider":{"type":"string"},"tokenAddress":{"type":"string"},"tokenSymbol":{"type":"string"},"withdrawalFeeBps":{"type":"integer","format":"int32","description":"Fee applied to a player-initiated withdrawal. Automatic winnings\npayouts are exempt because their advertised settlement is already net.","minimum":0}}},"chess_CheckLotteryPlaysRequest":{"type":"object","required":["tickets"],"properties":{"tickets":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryLineSelection"}}}},"chess_CheckLotteryPlaysResponse":{"type":"object","required":["drawId","resultHash","winningWhiteNumbers","winningPowerNumber","prizePerWinningTicketUsdc","tickets"],"properties":{"drawId":{"type":"string"},"prizePerWinningTicketUsdc":{"type":"string"},"resultHash":{"type":"string"},"tickets":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryPlayCheckResponse"}},"winningPowerNumber":{"type":"integer","format":"int32"},"winningWhiteNumbers":{"type":"array","items":{"type":"integer","format":"int32"}}}},"chess_ClockMode":{"type":"string","enum":["real_time","unlimited"]},"chess_Clocks":{"type":"object","required":["whiteMs","blackMs"],"properties":{"blackMs":{"type":"integer","format":"int64"},"whiteMs":{"type":"integer","format":"int64"}}},"chess_CoachActionTone":{"type":"string","enum":["neutral","positive","caution","critical"]},"chess_CoachCatalogResponse":{"type":"object","required":["version","maximumPoints","sections"],"properties":{"maximumPoints":{"type":"integer","format":"int32"},"sections":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachSectionResponse"}},"version":{"type":"integer","format":"int32"}}},"chess_CoachChapterResponse":{"type":"object","required":["key","title","instruction","fen","side","targetUci","hints","successMessage"],"properties":{"fen":{"type":"string"},"hints":{"type":"array","items":{"type":"string"}},"instruction":{"type":"string"},"key":{"type":"string"},"side":{"type":"string"},"successMessage":{"type":"string"},"targetUci":{"type":"string"},"title":{"type":"string"}}},"chess_CoachChoiceKind":{"type":"string","enum":["continue","undo"]},"chess_CoachExperience":{"type":"string","enum":["beginner","intermediate","advanced"]},"chess_CoachHintRequest":{"type":"object","required":["player","idempotencyKey"],"properties":{"expectedPly":{"type":["integer","null"],"format":"int32"},"idempotencyKey":{"type":"string"},"player":{"type":"string"}}},"chess_CoachHintResponse":{"type":"object","required":["id","matchId","ply","level","message","motif","actions","createdAt"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"level":{"type":"integer","format":"int32"},"matchId":{"type":"string"},"message":{"type":"string"},"motif":{"$ref":"#/components/schemas/chess_AnalysisMotif"},"ply":{"type":"integer","format":"int32"},"suggestedSan":{"type":["string","null"]},"suggestedUci":{"type":["string","null"],"description":"Revealed only by the third and final hint."}}},"chess_CoachHomeResponse":{"type":"object","required":["profile","earnedPoints","maximumPoints","trainingPositionCount","lessons"],"properties":{"earnedPoints":{"type":"integer","format":"int32"},"lessons":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachLessonStatusResponse"}},"maximumPoints":{"type":"integer","format":"int32"},"profile":{"$ref":"#/components/schemas/chess_CoachProfileResponse"},"recommendedLessonKey":{"type":["string","null"]},"trainingPositionCount":{"type":"integer","format":"int32"}}},"chess_CoachLessonAttemptRequest":{"type":"object","required":["player","uci","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"},"uci":{"type":"string"}}},"chess_CoachLessonAttemptResponse":{"type":"object","required":["id","player","lessonKey","chapterKey","attemptedUci","legal","correct","score","message","attempts","bestScore","completed","createdAt"],"properties":{"attemptedUci":{"type":"string"},"attempts":{"type":"integer","format":"int32"},"bestScore":{"type":"integer","format":"int32"},"chapterKey":{"type":"string"},"completed":{"type":"boolean"},"correct":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"legal":{"type":"boolean"},"lessonKey":{"type":"string"},"message":{"type":"string"},"nextHint":{"type":["string","null"]},"player":{"type":"string"},"score":{"type":"integer","format":"int32"}}},"chess_CoachLessonResponse":{"type":"object","required":["key","title","summary","difficulty","maximumPoints","prerequisiteLessonKeys","chapters"],"properties":{"chapters":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachChapterResponse"}},"difficulty":{"type":"integer","format":"int32"},"key":{"type":"string"},"maximumPoints":{"type":"integer","format":"int32"},"prerequisiteLessonKeys":{"type":"array","items":{"type":"string"}},"summary":{"type":"string"},"title":{"type":"string"}}},"chess_CoachLessonStatus":{"type":"string","enum":["locked","available","inProgress","completed"]},"chess_CoachLessonStatusResponse":{"type":"object","required":["lessonKey","status","earnedPoints","maximumPoints","completedChapters","totalChapters"],"properties":{"completedChapters":{"type":"integer","format":"int32"},"earnedPoints":{"type":"integer","format":"int32"},"lessonKey":{"type":"string"},"maximumPoints":{"type":"integer","format":"int32"},"status":{"$ref":"#/components/schemas/chess_CoachLessonStatus"},"totalChapters":{"type":"integer","format":"int32"}}},"chess_CoachMoveAttemptRequest":{"type":"object","required":["player","uci","idempotencyKey"],"properties":{"acceptWarning":{"type":"boolean","description":"Commits a previously warned move instead of asking the player to retry."},"expectedPly":{"type":["integer","null"],"format":"int32","description":"Optional stale-client guard. When supplied, it must equal the server ply."},"idempotencyKey":{"type":"string","description":"Must identify this attempted move. Reuse it when accepting a warning."},"player":{"type":"string"},"uci":{"type":"string"}}},"chess_CoachMoveAttemptResponse":{"type":"object","required":["attemptId","matchId","ply","status","classification","motif","attemptedUci","attemptedSan","message","canRetry","canOverride","canUndo","canContinue","actions","createdAt"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"attemptId":{"type":"string"},"attemptedSan":{"type":"string"},"attemptedUci":{"type":"string"},"bestSan":{"type":["string","null"]},"bestUci":{"type":["string","null"],"description":"Hidden while a warning is pending so retrying remains meaningful."},"canContinue":{"type":"boolean"},"canOverride":{"type":"boolean"},"canRetry":{"type":"boolean"},"canUndo":{"type":"boolean"},"centipawnLoss":{"type":["integer","null"],"format":"int32"},"classification":{"$ref":"#/components/schemas/chess_AnalysisClassification"},"createdAt":{"type":"string","format":"date-time"},"matchId":{"type":"string"},"matchState":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_MatchResponse"}]},"message":{"type":"string"},"motif":{"$ref":"#/components/schemas/chess_AnalysisMotif"},"ply":{"type":"integer","format":"int32"},"principalVariation":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/chess_ComputerCoachMoveStatus"},"winChanceLoss":{"type":["number","null"],"format":"double"}}},"chess_CoachPreferredMode":{"type":"string","enum":["learn","play","train","lessons"]},"chess_CoachProfileResponse":{"type":"object","required":["player","experience","onboardingComplete","preferredMode","createdAt","updatedAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"experience":{"$ref":"#/components/schemas/chess_CoachExperience"},"onboardingComplete":{"type":"boolean"},"player":{"type":"string"},"preferredMode":{"$ref":"#/components/schemas/chess_CoachPreferredMode"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_CoachProgressItemResponse":{"type":"object","required":["lessonKey","chapterKey","bestScore","lastScore","attempts","completed","createdAt","updatedAt"],"properties":{"attempts":{"type":"integer","format":"int32"},"bestScore":{"type":"integer","format":"int32"},"chapterKey":{"type":"string"},"completed":{"type":"boolean"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"lastScore":{"type":"integer","format":"int32"},"lessonKey":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_CoachProgressResponse":{"type":"object","required":["player","totalEntries","completedEntries","items"],"properties":{"completedEntries":{"type":"integer","format":"int32"},"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachProgressItemResponse"}},"player":{"type":"string"},"totalEntries":{"type":"integer","format":"int32"}}},"chess_CoachReviewActionRequest":{"type":"object","required":["player","attemptId"],"properties":{"attemptId":{"type":"string"},"expectedPly":{"type":["integer","null"],"format":"int32","description":"The current server ply expected by the client."},"player":{"type":"string"}}},"chess_CoachSectionResponse":{"type":"object","required":["key","title","summary","lessons"],"properties":{"key":{"type":"string"},"lessons":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachLessonResponse"}},"summary":{"type":"string"},"title":{"type":"string"}}},"chess_CoachStateQuery":{"type":"object","required":["player"],"properties":{"player":{"type":"string"}}},"chess_CoachTrainingAttemptRequest":{"type":"object","required":["uci","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"uci":{"type":"string"}}},"chess_CoachTrainingAttemptResponse":{"type":"object","required":["id","player","matchId","sourcePly","attemptedUci","legal","correct","attempts","hintLevel","message","actions","createdAt"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"attemptedUci":{"type":"string"},"attempts":{"type":"integer","format":"int32"},"correct":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"hintLevel":{"type":"integer","format":"int32"},"id":{"type":"string"},"legal":{"type":"boolean"},"matchId":{"type":"string"},"message":{"type":"string"},"player":{"type":"string"},"sourcePly":{"type":"integer","format":"int32"},"suggestedUci":{"type":["string","null"]}}},"chess_CoachTrainingItemResponse":{"type":"object","required":["matchId","ply","side","phase","motif","classification","fen","playedUci","playedSan","createdAt"],"properties":{"bestSan":{"type":["string","null"]},"bestUci":{"type":["string","null"]},"centipawnLoss":{"type":["integer","null"],"format":"int32"},"classification":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"fen":{"type":"string"},"matchId":{"type":"string"},"motif":{"type":"string"},"phase":{"type":"string"},"playedSan":{"type":"string"},"playedUci":{"type":"string"},"ply":{"type":"integer","format":"int32"},"principalVariation":{"type":["string","null"]},"side":{"type":"string"}}},"chess_CoachTrainingResponse":{"type":"object","required":["player","items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachTrainingItemResponse"}},"player":{"type":"string"}}},"chess_CoachUiAction":{"oneOf":[{"type":"object","required":["text","tone","type"],"properties":{"text":{"type":"string"},"tone":{"$ref":"#/components/schemas/chess_CoachActionTone"},"type":{"type":"string","enum":["say"]}}},{"type":"object","required":["from","to","tone","type"],"properties":{"from":{"type":"string"},"to":{"type":"string"},"tone":{"$ref":"#/components/schemas/chess_CoachActionTone"},"type":{"type":"string","enum":["drawArrow"]}}},{"type":"object","required":["id","label","action","type"],"properties":{"action":{"$ref":"#/components/schemas/chess_CoachChoiceKind"},"id":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["choice"]}}},{"type":"object","required":["hint","undo","menu","next","type"],"properties":{"hint":{"type":"boolean"},"menu":{"type":"boolean"},"next":{"type":"boolean"},"type":{"type":"string","enum":["setControls"]},"undo":{"type":"boolean"}}}],"description":"Presentation-neutral actions let web and mobile clients render the same\ncoaching state without embedding the teaching policy in either client."},"chess_ColorChoice":{"type":"string","description":"Preferred colour for the match creator.","enum":["white","black","random"]},"chess_ComputerCoachGameSummaryResponse":{"type":"object","required":["outcome","totalPlies","playerMoves","reviewedMoves","moveQuality","help","message"],"properties":{"finishedAt":{"type":["string","null"],"format":"date-time"},"help":{"$ref":"#/components/schemas/chess_ComputerCoachHelpStatsResponse"},"message":{"type":"string"},"moveQuality":{"$ref":"#/components/schemas/chess_ComputerCoachMoveQualityResponse"},"outcome":{"$ref":"#/components/schemas/chess_ComputerCoachOutcome"},"playerMoves":{"type":"integer","format":"int32"},"resultReason":{"type":["string","null"]},"reviewedMoves":{"type":"integer","format":"int32"},"totalPlies":{"type":"integer","format":"int32"}}},"chess_ComputerCoachHelpStatsResponse":{"type":"object","required":["hints","undos","usedHelp"],"properties":{"hints":{"type":"integer","format":"int32"},"undos":{"type":"integer","format":"int32"},"usedHelp":{"type":"boolean"}}},"chess_ComputerCoachMoveQualityResponse":{"type":"object","required":["best","good","inaccuracies","mistakes","blunders"],"properties":{"averageCentipawnLoss":{"type":["number","null"],"format":"double"},"averageWinChanceLoss":{"type":["number","null"],"format":"double"},"best":{"type":"integer","format":"int32"},"blunders":{"type":"integer","format":"int32"},"good":{"type":"integer","format":"int32"},"inaccuracies":{"type":"integer","format":"int32"},"mistakes":{"type":"integer","format":"int32"}}},"chess_ComputerCoachMoveStatus":{"type":"string","enum":["warning","applying","accepted","overridden","review","continued","undone","stale"]},"chess_ComputerCoachOutcome":{"type":"string","enum":["win","draw","loss","unresolved"]},"chess_ComputerCoachStateResponse":{"type":"object","required":["matchId","enabled","player","ply","canMove","awaitingResponse","hintLevel","actions"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"awaitingResponse":{"type":"boolean"},"canMove":{"type":"boolean"},"enabled":{"type":"boolean"},"hintLevel":{"type":"integer","format":"int32"},"matchId":{"type":"string"},"pendingReview":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_CoachMoveAttemptResponse"}]},"pendingWarning":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_CoachMoveAttemptResponse"}]},"player":{"type":"string"},"ply":{"type":"integer","format":"int32"},"summary":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_ComputerCoachGameSummaryResponse"}]}}},"chess_ComputerHintResponse":{"type":"object","required":["id","matchId","ply","suggestedUci","createdAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"matchId":{"type":"string"},"ply":{"type":"integer","format":"int32"},"suggestedUci":{"type":"string"}}},"chess_ComputerOpponentResponse":{"type":"object","required":["player","name","side","level","coachEnabled","hintsUsed"],"properties":{"coachEnabled":{"type":"boolean"},"hintsUsed":{"type":"integer","format":"int32"},"level":{"type":"integer","format":"int32"},"name":{"type":"string"},"player":{"type":"string"},"side":{"$ref":"#/components/schemas/chess_Side"},"wager":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_ComputerWagerResponse"}]}}},"chess_ComputerWagerResponse":{"type":"object","required":["stakeUsdc","houseExposureUsdc","potentialPayoutUsdc","drawPayoutUsdc","feeBps","status","payoutUsdc"],"properties":{"drawPayoutUsdc":{"type":"string","description":"Persisted draw return. New level-8 wagers return zero; legacy wagers\nretain the terms accepted when they were created."},"feeBps":{"type":"integer","format":"int32","description":"Applied only to the house-funded reward, never returned principal."},"houseExposureUsdc":{"type":"string"},"payoutUsdc":{"type":"string"},"potentialPayoutUsdc":{"type":"string"},"stakeUsdc":{"type":"string"},"status":{"type":"string"}}},"chess_ConfirmDepositRequest":{"type":"object","required":["player","txHash"],"properties":{"player":{"type":"string"},"txHash":{"type":"string"}}},"chess_CreateArenaRequest":{"type":"object","required":["organizer","name","durationMinutes"],"properties":{"durationMinutes":{"type":"integer","format":"int32"},"incrementSeconds":{"type":["integer","null"],"format":"int64"},"initialSeconds":{"type":["integer","null"],"format":"int64"},"maxPlayers":{"type":["integer","null"],"format":"int32"},"name":{"type":"string"},"organizer":{"type":"string"},"startDelaySeconds":{"type":"integer","format":"int64"}}},"chess_CreateComputerMatchRequest":{"type":"object","required":["player","level"],"properties":{"coach_enabled":{"type":"boolean","description":"Enables local, pre-move coaching for a free computer game. The flag is\npersisted so every client renders the same game mode. Coaching is never\nallowed in a staked game."},"color":{"$ref":"#/components/schemas/chess_ColorChoice","description":"Human player's preferred side. Random is resolved by the server."},"idempotency_key":{"type":["string","null"],"description":"Required for staked games so a retried request cannot reserve a second\nplayer stake or create a second funded match."},"increment_seconds":{"type":["integer","null"],"format":"int64","description":"Fischer increment for real-time games."},"initial_seconds":{"type":["integer","null"],"format":"int64","description":"Main clock per side for real-time games."},"level":{"type":"integer","format":"int32","description":"Lichess-style Stockfish strength, from 1 (easiest) to 8 (strongest)."},"player":{"type":"string","description":"Authenticated wallet that will occupy the human seat."},"stake_usdc":{"type":["string","null"],"description":"Optional player stake. Levels 5 through 8 accept money and all run the\nmaximum-strength level-8 engine. A reviewed win receives twice the\nplayer's stake. Omitted stays free."},"time_mode":{"$ref":"#/components/schemas/chess_ClockMode","description":"Deprecated compatibility field. Stockfish games are always untimed so\nan unavailable engine worker can never lose a game on time."}}},"chess_CreateDraughtsComputerMatchRequest":{"type":"object","required":["player","level"],"properties":{"coachEnabled":{"type":"boolean"},"color":{"$ref":"#/components/schemas/chess_draughts.ColorChoice"},"idempotencyKey":{"type":["string","null"]},"incrementSeconds":{"type":["integer","null"],"format":"int64"},"initialSeconds":{"type":["integer","null"],"format":"int64"},"level":{"type":"integer","format":"int32"},"player":{"type":"string"},"stakeUsdc":{"type":["string","null"],"description":"Optional player stake. Levels 1-3 are practice-only; levels 4-8 use\npersisted level-based house exposure."},"startingFen":{"type":["string","null"]},"timeMode":{"$ref":"#/components/schemas/chess_ClockMode"},"variant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.DraughtsVariant"}]}}},"chess_CreateMatchChatMessageRequest":{"type":"object","required":["room","text"],"properties":{"author":{"type":["string","null"],"description":"Optional author identity. In production the trusted\n`x-wallet-address` header becomes authoritative when present."},"room":{"$ref":"#/components/schemas/chess_MatchChatRoom","description":"Which room to post into."},"text":{"type":"string","description":"Chat line body."}}},"chess_CreateMatchHttpRequest":{"allOf":[{"$ref":"#/components/schemas/chess_CreateMatchRequest"},{"type":"object","properties":{"videoEnabled":{"type":"boolean"}}}],"description":"HTTP-only match options. Keeping video outside the core request preserves\nthe existing internal game API used by workers and integration tests."},"chess_CreateMatchRequest":{"type":"object","required":["creator"],"properties":{"allow_time_extensions":{"type":"boolean","description":"Allows either participant to spend one extension credit to add the same\namount to both clocks. Only available for unstaked PvP games."},"color":{"$ref":"#/components/schemas/chess_ColorChoice","description":"Colour the creator wants; defaults to random."},"creator":{"type":"string","description":"Wallet address of the player creating the challenge."},"increment_seconds":{"type":["integer","null"],"format":"int64","description":"Fischer increment per move in seconds (falls back to the service default)."},"initial_seconds":{"type":["integer","null"],"format":"int64","description":"Main clock per side in seconds (falls back to the service default)."},"rated":{"type":"boolean","description":"Whether this match should affect ratings. Defaults to true, like a rated\nchallenge on Lichess; set false for casual games."},"stake_usdc":{"type":["string","null"],"description":"Optional stake per player, denominated in USDC."}}},"chess_CreateSwissRequest":{"type":"object","required":["organizer","name","nbRounds"],"properties":{"draughtsVariant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.DraughtsVariant"}]},"entryFeeUsdc":{"type":["string","null"]},"forbiddenPairings":{"type":["string","null"]},"format":{"$ref":"#/components/schemas/chess_SwissFormat"},"game":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_SwissGameKind"}]},"incrementSeconds":{"type":["integer","null"],"format":"int64"},"initialSeconds":{"type":["integer","null"],"format":"int64"},"knockoutGamesPerTie":{"type":"integer","format":"int32"},"maxPlayers":{"type":["integer","null"],"format":"int32"},"name":{"type":"string"},"nbRounds":{"type":"integer","format":"int32"},"organizer":{"type":"string"},"password":{"type":["string","null"]},"prizePolicy":{"$ref":"#/components/schemas/chess_SwissPrizePolicy"},"startingFen":{"type":["string","null"]}}},"chess_CreateWithdrawalRequest":{"type":"object","required":["player","amountUsdc"],"properties":{"amountUsdc":{"type":"string"},"player":{"type":"string"},"toAddress":{"type":["string","null"]}}},"chess_DeleteMatchCommentRequest":{"type":"object","properties":{"player":{"type":["string","null"],"description":"Optional author identity. In production the trusted\n`x-wallet-address` header becomes authoritative when present."}}},"chess_DepositResponse":{"type":"object","required":["txHash","player","fromAddress","toAddress","amountUsdc","status"],"properties":{"amountUsdc":{"type":"string"},"confirmedAt":{"type":["string","null"],"format":"date-time"},"fromAddress":{"type":"string"},"player":{"type":"string"},"status":{"type":"string"},"toAddress":{"type":"string"},"txHash":{"type":"string"}}},"chess_DraughtsAnalysisPositionResponse":{"type":"object","required":["ply","side","phase","variant","timeControl","fen","classification","motif"],"properties":{"bestUci":{"type":["string","null"]},"classification":{"type":"string"},"fen":{"type":"string"},"loss":{"type":["integer","null"],"format":"int32"},"motif":{"type":"string"},"phase":{"type":"string"},"playedUci":{"type":["string","null"]},"player":{"type":["string","null"]},"ply":{"type":"integer","format":"int32"},"principalVariation":{"type":["string","null"]},"scoreAfter":{"type":["integer","null"],"format":"int32"},"scoreBefore":{"type":["integer","null"],"format":"int32"},"side":{"type":"string"},"timeControl":{"type":"string"},"variant":{"type":"string"}}},"chess_DraughtsAnalysisQueueQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"}}},"chess_DraughtsAnalysisQueueResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsAnalysisResponse"}}}},"chess_DraughtsAnalysisResponse":{"type":"object","required":["matchId","status","analysisTier","depth","attemptCount","createdAt","positions"],"properties":{"analysisTier":{"type":"string"},"attemptCount":{"type":"integer","format":"int32"},"createdAt":{"type":"string","format":"date-time"},"depth":{"type":"integer","format":"int32"},"finishedAt":{"type":["string","null"],"format":"date-time"},"lastError":{"type":["string","null"]},"matchId":{"type":"string"},"positions":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsAnalysisPositionResponse"}},"requestedBy":{"type":["string","null"]},"startedAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"summary":{}}},"chess_DraughtsBetResponse":{"type":"object","required":["id","matchId","bettor","outcome","stakeUsdc","status","payoutUsdc","createdAt"],"properties":{"bettor":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"matchId":{"type":"string"},"outcome":{"type":"string"},"payoutUsdc":{"type":"string"},"stakeUsdc":{"type":"string"},"status":{"type":"string"}}},"chess_DraughtsCoachProgressItemResponse":{"type":"object","required":["skillKey","level","attempts","successes","mastery","updatedAt"],"properties":{"attempts":{"type":"integer","format":"int32"},"lastMatchId":{"type":["string","null"]},"lastPly":{"type":["integer","null"],"format":"int32"},"level":{"type":"integer","format":"int32"},"mastery":{"type":"number","format":"double"},"skillKey":{"type":"string"},"successes":{"type":"integer","format":"int32"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_DraughtsCoachProgressResponse":{"type":"object","required":["player","items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsCoachProgressItemResponse"}},"player":{"type":"string"}}},"chess_DraughtsComputerHintResponse":{"type":"object","required":["id","matchId","ply","suggestedUci","createdAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"matchId":{"type":"string"},"ply":{"type":"integer","format":"int32"},"suggestedUci":{"type":"string"}}},"chess_DraughtsComputerOpponentResponse":{"type":"object","required":["player","name","side","level","coachEnabled","hintsUsed"],"properties":{"coachEnabled":{"type":"boolean"},"hintsUsed":{"type":"integer","format":"int32"},"level":{"type":"integer","format":"int32"},"name":{"type":"string"},"player":{"type":"string"},"side":{"$ref":"#/components/schemas/chess_draughts.Side"},"wager":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_DraughtsComputerWagerResponse"}]}}},"chess_DraughtsComputerWagerResponse":{"type":"object","required":["stakeUsdc","houseExposureUsdc","potentialPayoutUsdc","feeBps","status","payoutUsdc"],"properties":{"feeBps":{"type":"integer","format":"int32","description":"Applied only to the house-funded reward, never returned principal."},"houseExposureUsdc":{"type":"string"},"payoutUsdc":{"type":"string"},"potentialPayoutUsdc":{"type":"string"},"stakeUsdc":{"type":"string"},"status":{"type":"string"}}},"chess_DraughtsInsightBucketResponse":{"type":"object","required":["key","moves","averageLoss","maxLoss","latestAt"],"properties":{"averageLoss":{"type":"integer","format":"int64"},"key":{"type":"string"},"latestAt":{"type":"string","format":"date-time"},"maxLoss":{"type":"integer","format":"int64"},"moves":{"type":"integer","format":"int64"}}},"chess_DraughtsInsightQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"}}},"chess_DraughtsInsightsResponse":{"type":"object","required":["player","totalMistakes","motifs","phases","variants","sides","timeControls"],"properties":{"motifs":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsInsightBucketResponse"}},"phases":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsInsightBucketResponse"}},"player":{"type":"string"},"sides":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsInsightBucketResponse"}},"timeControls":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsInsightBucketResponse"}},"totalMistakes":{"type":"integer","format":"int64"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/chess_DraughtsInsightBucketResponse"}}}},"chess_DraughtsMarketOddsResponse":{"type":"object","required":["matchId","status","totalPoolUsdc","rakeBps","white","black","draw"],"properties":{"black":{"$ref":"#/components/schemas/chess_DraughtsOutcomePoolResponse"},"draw":{"$ref":"#/components/schemas/chess_DraughtsOutcomePoolResponse"},"matchId":{"type":"string"},"rakeBps":{"type":"integer","format":"int32"},"status":{"type":"string"},"totalPoolUsdc":{"type":"string"},"voidReason":{"type":["string","null"]},"white":{"$ref":"#/components/schemas/chess_DraughtsOutcomePoolResponse"},"winningOutcome":{"type":["string","null"]}}},"chess_DraughtsOutcomePoolResponse":{"type":"object","required":["poolUsdc"],"properties":{"decimalOdds":{"type":["string","null"]},"poolUsdc":{"type":"string"}}},"chess_DraughtsPerfKey":{"type":"string","enum":["ultraBullet","bullet","blitz","rapid","classical","standard","frisian","frysk","antidraughts","breakthrough","russian","brazilian"]},"chess_DrawResponseRequest":{"type":"object","required":["player","accept"],"properties":{"accept":{"type":"boolean","description":"True to accept the pending draw offer, false to decline it."},"player":{"type":"string"}}},"chess_ExtendMatchTimeRequest":{"type":"object","required":["player","seconds","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"},"seconds":{"type":"integer","format":"int32","description":"Supported values are 60, 300, or 600 seconds. Both clocks receive it."}}},"chess_FairPlayGameReportResponse":{"type":"object","required":["matchId","activation","moveCount","moves"],"properties":{"activation":{"type":"number","format":"double"},"matchId":{"type":"string"},"moveCount":{"type":"integer","format":"int32"},"moves":{"type":"array","items":{"$ref":"#/components/schemas/chess_FairPlayMoveReportResponse"}}}},"chess_FairPlayMatchQuery":{"type":"object","required":["player"],"properties":{"player":{"type":"string"}}},"chess_FairPlayMatchStatusResponse":{"type":"object","required":["matchId","status","fundsHeld","message","updatedAt"],"properties":{"fundsHeld":{"type":"boolean"},"matchId":{"type":"string"},"message":{"type":"string"},"status":{"$ref":"#/components/schemas/chess_FairPlayReviewStatus"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_FairPlayMoveReportResponse":{"type":"object","required":["matchId","ply","activation","engineMatch"],"properties":{"activation":{"type":"number","format":"double"},"ambiguity":{"type":["integer","null"],"format":"int32"},"cpLoss":{"type":["integer","null"],"format":"int32"},"elapsedMs":{"type":["integer","null"],"format":"int64"},"engineMatch":{"type":"boolean"},"loss":{"type":["number","null"],"format":"double"},"matchId":{"type":"string"},"odds":{"type":["number","null"],"format":"double"},"ply":{"type":"integer","format":"int32"},"rank":{"type":["integer","null"],"format":"int32"}}},"chess_FairPlayPlayerReportResponse":{"type":"object","required":["id","player","activation","gamesAnalyzed","modelVersion","trustedModel","shadow","createdAt","games"],"properties":{"activation":{"type":"number","format":"double"},"createdAt":{"type":"string","format":"date-time"},"games":{"type":"array","items":{"$ref":"#/components/schemas/chess_FairPlayGameReportResponse"}},"gamesAnalyzed":{"type":"integer","format":"int32"},"id":{"type":"string"},"modelVersion":{"type":"string"},"player":{"type":"string"},"shadow":{"type":"boolean"},"trustedModel":{"type":"boolean"}}},"chess_FairPlayResolution":{"type":"string","enum":["cleared","voided","reopened"]},"chess_FairPlayReviewActionResponse":{"type":"object","required":["id","action","reviewer","note","previousStatus","createdAt"],"properties":{"action":{"$ref":"#/components/schemas/chess_FairPlayResolution"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"note":{"type":"string"},"previousStatus":{"type":"string"},"reviewer":{"type":"string"}}},"chess_FairPlayReviewDetailResponse":{"type":"object","required":["review","reports","actions"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_FairPlayReviewActionResponse"}},"reports":{"type":"array","items":{"$ref":"#/components/schemas/chess_FairPlayPlayerReportResponse"}},"review":{"$ref":"#/components/schemas/chess_FairPlayReviewSummaryResponse"}}},"chess_FairPlayReviewListQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"},"status":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_FairPlayReviewStatus"}]}}},"chess_FairPlayReviewListResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_FairPlayReviewSummaryResponse"}}}},"chess_FairPlayReviewStatus":{"type":"string","enum":["pending","cleared","review","voided","failed_open"]},"chess_FairPlayReviewSummaryResponse":{"type":"object","required":["matchId","status","trustedModel","shadow","updatedAt"],"properties":{"matchId":{"type":"string"},"maxActivation":{"type":["number","null"],"format":"double"},"modelVersion":{"type":["string","null"]},"reason":{"type":["string","null"]},"shadow":{"type":"boolean"},"status":{"$ref":"#/components/schemas/chess_FairPlayReviewStatus"},"trustedModel":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_GameResult":{"type":"string","enum":["white","black","draw"]},"chess_GasHealthResponse":{"type":"object","description":"Result of the payout-rail health probe: a dry-run `wallet_prepareCalls` that\nnever signs or broadcasts. Lets ops confirm the gasless withdrawal path is\nreachable and sponsoring without moving funds.","required":["ok","configured","detail"],"properties":{"configured":{"type":"boolean","description":"Whether gas sponsorship is configured at all (a policy id is present)."},"detail":{"type":"string","description":"The wallet-API URL used on success, or the failure detail."},"ok":{"type":"boolean","description":"True when the Wallet API prepared a sponsored user operation successfully."}}},"chess_GetArenaQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"},"offset":{"type":["integer","null"],"format":"int64"},"player":{"type":["string","null"]}}},"chess_HealthStatus":{"type":"object","description":"Payload returned by `GET /health` — matches the platform `HealthStatus`\n(`@tsionark/types`): Docker healthchecks and monitors depend on this shape.","required":["status","service","uptimeSeconds"],"properties":{"service":{"type":"string"},"status":{"type":"string","description":"\"ok\" | \"degraded\""},"uptimeSeconds":{"type":"integer","format":"int64","minimum":0}}},"chess_InsightBucketResponse":{"type":"object","required":["key","games","averageCpLoss","maxCpLoss","latestAt"],"properties":{"averageCpLoss":{"type":"integer","format":"int32"},"games":{"type":"integer","format":"int32"},"key":{"type":"string"},"latestAt":{"type":"string","format":"date-time"},"maxCpLoss":{"type":"integer","format":"int32"}}},"chess_InsightQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"description":"Maximum buckets to return per dimension.","minimum":0}}},"chess_JoinArenaRequest":{"type":"object","required":["name"],"properties":{"countryCode":{"type":["string","null"]},"name":{"type":"string"},"rating":{"type":["integer","null"],"format":"int32"},"walletAddress":{"type":["string","null"]}}},"chess_JoinMatchRequest":{"type":"object","required":["player"],"properties":{"player":{"type":"string","description":"Wallet address of the joining opponent."}}},"chess_JoinSwissRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"password":{"type":["string","null"]},"walletAddress":{"type":["string","null"]}}},"chess_ListArenaQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"},"status":{"type":["string","null"]}}},"chess_LotteryBallPoolResponse":{"type":"object","required":["key","label","pickCount","numberMin","numberMax"],"properties":{"key":{"type":"string"},"label":{"type":"string"},"numberMax":{"type":"integer","format":"int32"},"numberMin":{"type":"integer","format":"int32","minimum":0},"pickCount":{"type":"integer","format":"int32"}}},"chess_LotteryConfigResponse":{"type":"object","required":["enabled","automated","authenticationRequired","salesDurationSeconds","salesCloseBeforeDrawSeconds","maxQuickPicksPerRequest","uniqueCombinationsRequired","playerVerificationEnforced","rule"],"properties":{"authenticationRequired":{"type":"boolean"},"automated":{"type":"boolean"},"enabled":{"type":"boolean"},"maxQuickPicksPerRequest":{"type":"integer","minimum":0},"playerVerificationEnforced":{"type":"boolean"},"rule":{"$ref":"#/components/schemas/chess_LotteryRuleResponse"},"salesCloseBeforeDrawSeconds":{"type":"integer","format":"int64"},"salesDurationSeconds":{"type":"integer","format":"int64"},"ticketLimitPerWalletPerDraw":{"type":["integer","null"],"format":"int64","description":"`None` means the application imposes no per-wallet ticket count cap.","minimum":0},"uniqueCombinationsRequired":{"type":"boolean"}}},"chess_LotteryDrawResponse":{"type":"object","required":["id","sequence","ruleVersion","status","salesOpenAt","salesCloseAt","drawAt","totalTickets","totalPlayers","currentPoolUsdc","broughtForwardUsdc","advertisedJackpotUsdc","cashValueUsdc","platformShareBps","payoutUsdc","platformRevenueUsdc","payoutPerWinningTicketUsdc","rolloverUsdc","refundedUsdc","winningTicketCount","randomnessProvider","randomnessChainHash","randomnessRound","randomnessRoundAt","randomnessCommitment"],"properties":{"advertisedJackpotUsdc":{"type":"string"},"broughtForwardUsdc":{"type":"string"},"cancellationReason":{"type":["string","null"]},"cashValueUsdc":{"type":"string","description":"Amount available to exact-match winners after the versioned platform\nshare. It is paid directly in USDC with no annuity conversion."},"currentPoolUsdc":{"type":"string"},"drawAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"payoutPerWinningTicketUsdc":{"type":"string"},"payoutUsdc":{"type":"string"},"platformRevenueUsdc":{"type":"string"},"platformShareBps":{"type":"integer","format":"int32"},"randomnessChainHash":{"type":"string"},"randomnessCommitment":{"type":"string"},"randomnessProvider":{"type":"string"},"randomnessRound":{"type":"integer","format":"int64"},"randomnessRoundAt":{"type":"string","format":"date-time"},"refundedUsdc":{"type":"string"},"result":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_LotteryDrawResultResponse"}]},"rolloverUsdc":{"type":"string"},"ruleVersion":{"type":"integer","format":"int32"},"salesCloseAt":{"type":"string","format":"date-time"},"salesOpenAt":{"type":"string","format":"date-time"},"sequence":{"type":"integer","format":"int64"},"settledAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"totalPlayers":{"type":"integer","format":"int32"},"totalTickets":{"type":"integer","format":"int32"},"winningTicketCount":{"type":"integer","format":"int32"}}},"chess_LotteryDrawResultResponse":{"type":"object","required":["drawId","whiteNumbers","powerNumber","randomnessRound","randomnessSignature","randomnessValue","resultHash","drawnAt"],"properties":{"drawId":{"type":"string"},"drawnAt":{"type":"string","format":"date-time"},"powerNumber":{"type":"integer","format":"int32"},"randomnessRound":{"type":"integer","format":"int64"},"randomnessSignature":{"type":"string"},"randomnessValue":{"type":"string"},"resultHash":{"type":"string"},"whiteNumbers":{"type":"array","items":{"type":"integer","format":"int32"}}}},"chess_LotteryEligibilityResponse":{"type":"object","required":["player","eligible","status","verificationRequired","ageVerified","identityVerified","ticketsPurchasedLast24h"],"properties":{"ageVerified":{"type":"boolean"},"dailyTicketLimit":{"type":["integer","null"],"format":"int32"},"eligible":{"type":"boolean"},"identityVerified":{"type":"boolean"},"jurisdiction":{"type":["string","null"]},"player":{"type":"string"},"reason":{"type":["string","null"]},"selfExcludedUntil":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"ticketsPurchasedLast24h":{"type":"integer","format":"int64"},"verificationRequired":{"type":"boolean"}}},"chess_LotteryLineSelection":{"type":"object","required":["whiteNumbers","powerNumber"],"properties":{"powerNumber":{"type":"integer","format":"int32","description":"The single red Powerball selected for this play.","minimum":0},"whiteNumbers":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"One ticket combination: exactly five unique white balls. Input\norder is normalized ascending by the backend."}}},"chess_LotteryPlayCheckResponse":{"type":"object","required":["index","whiteNumbers","powerNumber","matchedWhiteCount","powerballMatched","jackpotMatch"],"properties":{"index":{"type":"integer","minimum":0},"jackpotMatch":{"type":"boolean"},"matchedWhiteCount":{"type":"integer","format":"int32","minimum":0},"powerNumber":{"type":"integer","format":"int32","minimum":0},"powerballMatched":{"type":"boolean"},"whiteNumbers":{"type":"array","items":{"type":"integer","format":"int32","minimum":0}}}},"chess_LotteryPrizeTierResponse":{"type":"object","required":["key","whiteMatches","powerballMatch","payoutPolicy","oddsDenominator"],"properties":{"key":{"type":"string"},"oddsDenominator":{"type":"integer","format":"int64","minimum":0},"payoutPolicy":{"type":"string"},"powerballMatch":{"type":"boolean"},"whiteMatches":{"type":"integer","format":"int32","minimum":0}}},"chess_LotteryRuleResponse":{"type":"object","required":["version","slug","currency","ballPools","whitePickCount","whiteNumberMin","whiteNumberMax","powerPickCount","powerNumberMin","powerNumberMax","pricePerTicketUsdc","minimumPaidTickets","minimumPaidPlayers","prizePolicy","platformShareBps","winnerShareBps","prizeTiers","availableTicketCombinations","rolloverOnNoJackpotWinner","winningCondition"],"properties":{"availableTicketCombinations":{"type":"integer","format":"int64","minimum":0},"ballPools":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryBallPoolResponse"},"description":"Ordered selector steps for the frontend ticket builder: white balls first,\nthen the red Powerball."},"currency":{"type":"string"},"minimumPaidPlayers":{"type":"integer","format":"int32"},"minimumPaidTickets":{"type":"integer","format":"int32"},"platformShareBps":{"type":"integer","format":"int32"},"powerNumberMax":{"type":"integer","format":"int32"},"powerNumberMin":{"type":"integer","format":"int32","minimum":0},"powerPickCount":{"type":"integer","format":"int32","minimum":0},"pricePerTicketUsdc":{"type":"string"},"prizePolicy":{"type":"string"},"prizeTiers":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryPrizeTierResponse"}},"rolloverOnNoJackpotWinner":{"type":"boolean"},"slug":{"type":"string"},"version":{"type":"integer","format":"int32"},"whiteNumberMax":{"type":"integer","format":"int32"},"whiteNumberMin":{"type":"integer","format":"int32","minimum":0},"whitePickCount":{"type":"integer","format":"int32"},"winnerShareBps":{"type":"integer","format":"int32"},"winningCondition":{"type":"string"}}},"chess_LotteryTicketResponse":{"type":"object","required":["id","drawId","player","receiptHash","priceUsdc","whiteNumbers","powerNumber","status","payoutUsdc","acceptedAt"],"properties":{"acceptedAt":{"type":"string","format":"date-time"},"drawId":{"type":"string"},"id":{"type":"string"},"payoutUsdc":{"type":"string"},"player":{"type":"string"},"powerNumber":{"type":"integer","format":"int32"},"priceUsdc":{"type":"string"},"receiptHash":{"type":"string"},"settledAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"whiteNumbers":{"type":"array","items":{"type":"integer","format":"int32"}}}},"chess_MakeMoveRequest":{"type":"object","required":["player","uci"],"properties":{"player":{"type":"string","description":"Wallet address of the player making the move."},"uci":{"type":"string","description":"The move in UCI long algebraic form (e.g. \"e2e4\", \"e7e8q\")."}}},"chess_MarketOddsResponse":{"type":"object","description":"Live market view: pooled stakes and implied odds for each outcome.","required":["matchId","status","totalPoolUsdc","rakeBps","white","black","draw"],"properties":{"black":{"$ref":"#/components/schemas/chess_OutcomePool"},"draw":{"$ref":"#/components/schemas/chess_OutcomePool"},"matchId":{"type":"string"},"rakeBps":{"type":"integer","format":"int32"},"status":{"type":"string","description":"`open`, `settled`, or `voided` (`open` reported for a market with no bets yet)."},"totalPoolUsdc":{"type":"string"},"voidReason":{"type":["string","null"]},"white":{"$ref":"#/components/schemas/chess_OutcomePool"},"winningOutcome":{"type":["string","null"]}}},"chess_MatchAnalysisResponse":{"type":"object","required":["matchId","analysed","status","requestOrigin","requestCount","depth","tier","queuedAt","updatedAt","createdAt","summaries","moves"],"properties":{"analysed":{"type":"boolean"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"depth":{"type":"integer","format":"int32"},"engineName":{"type":["string","null"]},"failure":{"type":["string","null"]},"matchId":{"type":"string"},"moves":{"type":"array","items":{"$ref":"#/components/schemas/chess_AnalysisMoveResponse"}},"queuedAt":{"type":"string","format":"date-time"},"requestCount":{"type":"integer","format":"int32"},"requestOrigin":{"$ref":"#/components/schemas/chess_AnalysisRequestOrigin"},"requestedBy":{"type":["string","null"]},"startedAt":{"type":["string","null"],"format":"date-time"},"status":{"$ref":"#/components/schemas/chess_AnalysisStatus"},"summaries":{"type":"array","items":{"$ref":"#/components/schemas/chess_AnalysisPlayerSummaryResponse"}},"tier":{"$ref":"#/components/schemas/chess_AnalysisTier"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_MatchChatMessageResponse":{"type":"object","required":["id","matchId","room","author","text","createdAt"],"properties":{"author":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int64"},"matchId":{"type":"string"},"room":{"$ref":"#/components/schemas/chess_MatchChatRoom"},"text":{"type":"string"}}},"chess_MatchChatMessagesResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_MatchChatMessageResponse"}}}},"chess_MatchChatQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64","description":"Maximum rows to return (default 50, capped at 100)."},"player":{"type":["string","null"],"description":"Optional authenticated actor for the private player room. When the\ntrusted proxy sends `x-wallet-address`, that header wins."},"room":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_MatchChatRoom","description":"Chat room to read; spectator chat is the public default."}]}}},"chess_MatchChatRoom":{"type":"string","description":"Which match room a chat message belongs to.","enum":["player","spectator"]},"chess_MatchCommentResponse":{"type":"object","required":["id","matchId","ply","fen","author","text","createdAt","updatedAt"],"properties":{"author":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"fen":{"type":"string"},"id":{"type":"string"},"matchId":{"type":"string"},"ply":{"type":"integer","format":"int32"},"text":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_MatchCommentsQuery":{"type":"object","properties":{"ply":{"type":["integer","null"],"format":"int32","description":"Optional ply filter. `0` is the starting position, `1` the first move,\netc. Omit to fetch all comments."}}},"chess_MatchCommentsResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_MatchCommentResponse"}}}},"chess_MatchListResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_MatchResponse"}}}},"chess_MatchNoteQuery":{"type":"object","properties":{"player":{"type":["string","null"],"description":"Optional viewer identity. In production the trusted\n`x-wallet-address` header becomes authoritative when present."}}},"chess_MatchNoteResponse":{"type":"object","required":["matchId","player","text"],"properties":{"createdAt":{"type":["string","null"],"format":"date-time"},"matchId":{"type":"string"},"player":{"type":"string"},"text":{"type":"string"},"updatedAt":{"type":["string","null"],"format":"date-time"}}},"chess_MatchPlayerRatingResponse":{"type":"object","properties":{"diff":{"type":["integer","null"],"format":"int32"},"provisional":{"type":["boolean","null"]},"rating":{"type":["integer","null"],"format":"int32"}}},"chess_MatchRatingResponse":{"type":"object","required":["rated","white","black"],"properties":{"black":{"$ref":"#/components/schemas/chess_MatchPlayerRatingResponse"},"perfKey":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_PerfKey"}]},"rated":{"type":"boolean"},"white":{"$ref":"#/components/schemas/chess_MatchPlayerRatingResponse"}}},"chess_MatchRematchStateResponse":{"type":"object","properties":{"nextMatchId":{"type":["string","null"]},"offeredBy":{"type":["string","null"]}}},"chess_MatchResponse":{"type":"object","required":["id","inviteCode","liveTopic","videoEnabled","status","fen","turn","ply","timeControl","clocks","timeExtensions","clockUpdatedAt","takeback","rematch","rating","createdAt"],"properties":{"black":{"type":["string","null"]},"blackCountryCode":{"type":["string","null"]},"blackDisplayName":{"type":["string","null"]},"clockUpdatedAt":{"type":"string","format":"date-time","description":"Server timestamp at which the persisted clock banks were current."},"clocks":{"$ref":"#/components/schemas/chess_Clocks"},"computer":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_ComputerOpponentResponse","description":"Present only when one seat is controlled by the backend Stockfish worker."}]},"createdAt":{"type":"string","format":"date-time"},"drawOfferBy":{"type":["string","null"]},"fen":{"type":"string"},"finishedAt":{"type":["string","null"],"format":"date-time"},"id":{"type":"string"},"inviteCode":{"type":"string"},"liveTopic":{"type":"string"},"loser":{"type":["string","null"],"description":"Wallet address of the losing player; `null` for a draw or an unfinished match."},"ply":{"type":"integer","format":"int32"},"rating":{"$ref":"#/components/schemas/chess_MatchRatingResponse"},"rematch":{"$ref":"#/components/schemas/chess_MatchRematchStateResponse"},"result":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_GameResult"}]},"resultReason":{"type":["string","null"]},"startedAt":{"type":["string","null"],"format":"date-time"},"status":{"$ref":"#/components/schemas/chess_MatchStatus"},"takeback":{"$ref":"#/components/schemas/chess_MatchTakebackStateResponse"},"timeControl":{"$ref":"#/components/schemas/chess_TimeControl"},"timeExtensions":{"$ref":"#/components/schemas/chess_MatchTimeExtensionStateResponse"},"turn":{"$ref":"#/components/schemas/chess_Side"},"videoEnabled":{"type":"boolean"},"wager":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_MatchWagerResponse"}]},"white":{"type":["string","null"]},"whiteCountryCode":{"type":["string","null"]},"whiteDisplayName":{"type":["string","null"]},"winner":{"type":["string","null"],"description":"Wallet address of the winning player; `null` for a draw or an unfinished match."}}},"chess_MatchStatus":{"type":"string","enum":["waiting","active","finished","aborted"]},"chess_MatchTakebackStateResponse":{"type":"object","required":["white","black","takebackable"],"properties":{"black":{"type":"boolean"},"takebackable":{"type":"boolean"},"white":{"type":"boolean"}}},"chess_MatchTimeExtensionStateResponse":{"type":"object","required":["allowed","used","totalSeconds","maxUses","maxTotalSeconds"],"properties":{"allowed":{"type":"boolean"},"maxTotalSeconds":{"type":"integer","format":"int32"},"maxUses":{"type":"integer","format":"int32"},"totalSeconds":{"type":"integer","format":"int32"},"used":{"type":"integer","format":"int32"}}},"chess_MatchVideoRole":{"type":"string","enum":["player","spectator"]},"chess_MatchVideoTokenRequest":{"type":"object","properties":{"player":{"type":["string","null"],"description":"Match seat name for Arena/Swiss games. Ordinary wallet matches may omit it."}}},"chess_MatchVideoTokenResponse":{"type":"object","description":"Ark Stream token response with enough room metadata for the chess client to\nrender its role explicitly.","required":["serverUrl","participantToken","roomName","participantIdentity","role","expiresAt"],"properties":{"expiresAt":{"type":"string","format":"date-time"},"participantIdentity":{"type":"string"},"participantToken":{"type":"string"},"role":{"$ref":"#/components/schemas/chess_MatchVideoRole"},"roomName":{"type":"string"},"serverUrl":{"type":"string"}}},"chess_MatchWagerResponse":{"type":"object","required":["stakeUsdc","feeBps","creatorPlayer","creatorLocked","opponentLocked","status","fairPlayStatus"],"properties":{"creatorLocked":{"type":"boolean"},"creatorPlayer":{"type":"string"},"fairPlayHeldAt":{"type":["string","null"],"format":"date-time"},"fairPlayReleasedAt":{"type":["string","null"],"format":"date-time"},"fairPlayStatus":{"type":"string"},"feeBps":{"type":"integer","format":"int32"},"opponentLocked":{"type":"boolean"},"opponentPlayer":{"type":["string","null"]},"settledAt":{"type":["string","null"],"format":"date-time"},"stakeUsdc":{"type":"string"},"status":{"type":"string"},"winnerPlayer":{"type":["string","null"]}}},"chess_MoveResponse":{"type":"object","required":["ply","uci","san","fenAfter","byPlayer","createdAt"],"properties":{"byPlayer":{"type":"string"},"clockMsRemaining":{"type":["integer","null"],"format":"int64"},"createdAt":{"type":"string","format":"date-time"},"fenAfter":{"type":"string"},"ply":{"type":"integer","format":"int32"},"san":{"type":"string"},"uci":{"type":"string"}}},"chess_MoveResultResponse":{"type":"object","description":"Returned by `POST /matches/:id/moves` — the applied move plus the new state.","required":["match","move"],"properties":{"match":{"$ref":"#/components/schemas/chess_MatchResponse"},"move":{"$ref":"#/components/schemas/chess_MoveResponse"}}},"chess_MovesResponse":{"type":"object","required":["moves"],"properties":{"moves":{"type":"array","items":{"$ref":"#/components/schemas/chess_MoveResponse"}}}},"chess_NarratedLineResponse":{"type":"object","required":["text"],"properties":{"speech":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_PuzzleSpeechReferenceResponse"}]},"text":{"type":"string"}}},"chess_OutcomePool":{"type":"object","description":"One outcome's pooled stake and pari-mutuel decimal odds.","required":["poolUsdc"],"properties":{"decimalOdds":{"type":["string","null"],"description":"Decimal odds = total pool / this outcome's pool (payout per unit staked if\nthis outcome wins, before rake). `null` when this outcome has no stake."},"poolUsdc":{"type":"string"}}},"chess_PerfKey":{"type":"string","enum":["ultraBullet","bullet","blitz","rapid","classical","standard"]},"chess_PgnResponse":{"type":"object","required":["pgn"],"properties":{"pgn":{"type":"string","description":"The game rendered as a PGN document."}}},"chess_PlaceBetRequest":{"type":"object","description":"Place a spectator bet on a match outcome.","required":["matchId","bettor","outcome","stakeUsdc"],"properties":{"bettor":{"type":"string","description":"The bettor's wallet address (must not be one of the two players)."},"matchId":{"type":"string","description":"The match to bet on."},"outcome":{"type":"string","description":"Outcome backed: `white`, `black`, or `draw`."},"stakeUsdc":{"type":"string","description":"Stake in USDC (e.g. \"5\" or \"2.5\")."}}},"chess_PlaceDraughtsBetRequest":{"type":"object","required":["matchId","bettor","outcome","stakeUsdc","idempotencyKey"],"properties":{"bettor":{"type":"string"},"idempotencyKey":{"type":"string"},"matchId":{"type":"string"},"outcome":{"type":"string"},"stakeUsdc":{"type":"string"}}},"chess_PlaceSwissBetRequest":{"type":"object","required":["bettor","predictedPlayerId","stakeUsdc","idempotencyKey"],"properties":{"bettor":{"type":"string"},"idempotencyKey":{"type":"string"},"predictedPlayerId":{"type":"string"},"stakeUsdc":{"type":"string"}}},"chess_PlayerActionRequest":{"type":"object","required":["player"],"properties":{"player":{"type":"string","description":"Wallet address of the player performing the action."}}},"chess_PlayerBalanceResponse":{"type":"object","required":["player","availableUsdc","lockedUsdc","lockedMatchUsdc","lockedSwissUsdc","lockedBetUsdc","lockedLotteryUsdc","pendingWithdrawalUsdc","lockedOtherUsdc","totalUsdc"],"properties":{"availableUsdc":{"type":"string"},"lockedBetUsdc":{"type":"string"},"lockedLotteryUsdc":{"type":"string"},"lockedMatchUsdc":{"type":"string"},"lockedOtherUsdc":{"type":"string"},"lockedSwissUsdc":{"type":"string"},"lockedUsdc":{"type":"string"},"pendingWithdrawalUsdc":{"type":"string"},"player":{"type":"string"},"totalUsdc":{"type":"string"}}},"chess_PlayerPerfResponse":{"type":"object","required":["perfKey","rating","deviation","provisional","games"],"properties":{"deviation":{"type":"integer","format":"int32"},"games":{"type":"integer","format":"int32"},"latestAt":{"type":["string","null"],"format":"date-time"},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"provisional":{"type":"boolean"},"rating":{"type":"integer","format":"int32"}}},"chess_PlayerRatingChartResponse":{"type":"object","required":["player","perfKey","range","points"],"properties":{"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"player":{"type":"string"},"points":{"type":"array","items":{"$ref":"#/components/schemas/chess_RatingChartPointResponse"}},"range":{"type":"string"}}},"chess_PlayerRatingHistoryResponse":{"type":"object","required":["player","perfKey","items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_RatingHistoryEntryResponse"}},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"player":{"type":"string"}}},"chess_PlayerRatingStatsResponse":{"type":"object","required":["player","perfKey","rating","deviation","provisional","games","record","highestRating","lowestRating","ratingProgress"],"properties":{"countryCode":{"type":["string","null"]},"deviation":{"type":"integer","format":"int32"},"displayName":{"type":["string","null"]},"games":{"type":"integer","format":"int32"},"globalRank":{"type":["integer","null"],"format":"int64"},"highestAt":{"type":["string","null"],"format":"date-time"},"highestRating":{"type":"integer","format":"int32"},"lowestAt":{"type":["string","null"],"format":"date-time"},"lowestRating":{"type":"integer","format":"int32"},"percentile":{"type":["number","null"],"format":"double"},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"player":{"type":"string"},"provisional":{"type":"boolean"},"rating":{"type":"integer","format":"int32"},"ratingProgress":{"type":"integer","format":"int32"},"record":{"$ref":"#/components/schemas/chess_RatingRecordResponse"}}},"chess_PlayerRatingsResponse":{"type":"object","required":["player","skillLevel","initialRating","onboardingLocked","items"],"properties":{"initialRating":{"type":"integer","format":"int32"},"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_PlayerPerfResponse"}},"onboardingLocked":{"type":"boolean"},"player":{"type":"string"},"skillLevel":{"$ref":"#/components/schemas/chess_RatingSkillLevel"}}},"chess_ProductAccessResponse":{"type":"object","required":["player","coachActive","hintCredits","timeExtensionCredits","premiumReviewCredits","updatedAt"],"properties":{"coachActive":{"type":"boolean"},"coachUntil":{"type":["string","null"],"format":"date-time"},"hintCredits":{"type":"integer","format":"int32"},"player":{"type":"string"},"premiumReviewCredits":{"type":"integer","format":"int32"},"timeExtensionCredits":{"type":"integer","format":"int32"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_ProductCatalogItemResponse":{"type":"object","required":["key","name","description","priceUsdc"],"properties":{"description":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"priceUsdc":{"type":"string"}}},"chess_ProductCatalogResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_ProductCatalogItemResponse"}}}},"chess_ProductPurchaseResponse":{"type":"object","required":["id","player","productKey","priceUsdc","status","createdAt","access"],"properties":{"access":{"$ref":"#/components/schemas/chess_ProductAccessResponse"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"player":{"type":"string"},"priceUsdc":{"type":"string"},"productKey":{"type":"string"},"status":{"type":"string"}}},"chess_PurchaseLotteryTicketRequest":{"type":"object","required":["player","whiteNumbers","powerNumber","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"},"powerNumber":{"type":"integer","format":"int32","description":"The single red Powerball for this ticket.","minimum":0},"whiteNumbers":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Exactly five unique white balls for this ticket."}}},"chess_PurchaseProductRequest":{"type":"object","required":["player","productKey","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"},"productKey":{"type":"string"}}},"chess_PuzzleAttemptRequest":{"type":"object","required":["player","uci","solutionPly","idempotencyKey"],"properties":{"durationMs":{"type":["integer","null"],"format":"int32"},"hintUsed":{"type":"boolean"},"idempotencyKey":{"type":"string"},"player":{"type":"string"},"solutionPly":{"type":"integer","format":"int32","description":"Zero-based index in the solution continuation. Player plies are 0, 2, 4, ..."},"uci":{"type":"string"}}},"chess_PuzzleAttemptResponse":{"type":"object","required":["puzzleId","attemptedUci","legal","correct","completed","nextFen","nextSolutionPly","message"],"properties":{"attemptedUci":{"type":"string"},"completed":{"type":"boolean"},"correct":{"type":"boolean"},"legal":{"type":"boolean"},"message":{"type":"string"},"nextFen":{"type":"string"},"nextSolutionPly":{"type":"integer","format":"int32"},"opponentMove":{"type":["string","null"]},"puzzleId":{"type":"string"},"speech":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_PuzzleSpeechReferenceResponse"}]}}},"chess_PuzzleCatalogStatsResponse":{"type":"object","required":["source","puzzleCount","voiceEnabled"],"properties":{"maximumRating":{"type":["integer","null"],"format":"int32"},"minimumRating":{"type":["integer","null"],"format":"int32"},"puzzleCount":{"type":"integer","format":"int64"},"source":{"type":"string"},"voiceEnabled":{"type":"boolean"}}},"chess_PuzzleNarrationResponse":{"type":"object","required":["introduction","hint","success"],"properties":{"hint":{"$ref":"#/components/schemas/chess_NarratedLineResponse"},"introduction":{"$ref":"#/components/schemas/chess_NarratedLineResponse"},"success":{"$ref":"#/components/schemas/chess_NarratedLineResponse"}}},"chess_PuzzleResponse":{"type":"object","required":["id","fen","lastMove","sideToMove","rating","ratingDeviation","popularity","playCount","themes","openingTags","sourceUrl","playerMoveCount","narration"],"properties":{"fen":{"type":"string","description":"Position shown to the solver, after the source game's final opponent move."},"id":{"type":"string"},"lastMove":{"type":"string"},"narration":{"$ref":"#/components/schemas/chess_PuzzleNarrationResponse"},"openingTags":{"type":"array","items":{"type":"string"}},"playCount":{"type":"integer","format":"int64"},"playerMoveCount":{"type":"integer","format":"int32"},"popularity":{"type":"integer","format":"int32"},"rating":{"type":"integer","format":"int32"},"ratingDeviation":{"type":"integer","format":"int32"},"sideToMove":{"type":"string"},"sourceUrl":{"type":"string"},"themes":{"type":"array","items":{"type":"string"}}}},"chess_PuzzleSpeechAlignmentResponse":{"type":"object","required":["key","alignment"],"properties":{"alignment":{},"key":{"type":"string"}}},"chess_PuzzleSpeechReferenceResponse":{"type":"object","required":["key","audioUrl","alignmentUrl"],"properties":{"alignmentUrl":{"type":"string"},"audioUrl":{"type":"string"},"key":{"type":"string"}}},"chess_QueuedAnalysisSummaryResponse":{"type":"object","required":["matchId","status","requestOrigin","depth","tier","queuedAt"],"properties":{"depth":{"type":"integer","format":"int32"},"matchId":{"type":"string"},"queuedAt":{"type":"string","format":"date-time"},"requestOrigin":{"$ref":"#/components/schemas/chess_AnalysisRequestOrigin"},"requestedBy":{"type":["string","null"]},"startedAt":{"type":["string","null"],"format":"date-time"},"status":{"$ref":"#/components/schemas/chess_AnalysisStatus"},"tier":{"$ref":"#/components/schemas/chess_AnalysisTier"}}},"chess_QuickPickRequest":{"type":"object","required":["count"],"properties":{"count":{"type":"integer","minimum":0}}},"chess_QuickPickResponse":{"type":"object","required":["tickets"],"properties":{"tickets":{"type":"array","items":{"$ref":"#/components/schemas/chess_LotteryLineSelection"}}}},"chess_RatingChartPointResponse":{"type":"object","required":["rating","at"],"properties":{"at":{"type":"string","format":"date-time"},"matchId":{"type":["string","null"]},"rating":{"type":"integer","format":"int32"}}},"chess_RatingChartRange":{"type":"string","enum":["7d","30d","90d","1y","all"]},"chess_RatingHistoryEntryResponse":{"type":"object","required":["matchId","perfKey","ratingBefore","ratingAfter","ratingDiff","createdAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"matchId":{"type":"string"},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"ratingAfter":{"type":"integer","format":"int32"},"ratingBefore":{"type":"integer","format":"int32"},"ratingDiff":{"type":"integer","format":"int32"}}},"chess_RatingLeaderboardCountriesResponse":{"type":"object","required":["perfKey","activeWithinDays","totalPlayers","items"],"properties":{"activeWithinDays":{"type":"integer","format":"int64"},"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_RatingLeaderboardCountryResponse"}},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"totalPlayers":{"type":"integer","format":"int64"}}},"chess_RatingLeaderboardCountryResponse":{"type":"object","required":["countryCode","playerCount"],"properties":{"countryCode":{"type":"string"},"playerCount":{"type":"integer","format":"int64"}}},"chess_RatingLeaderboardPlayerResponse":{"type":"object","required":["rank","player","rating","deviation","games","wins","draws","losses","ratingProgress"],"properties":{"countryCode":{"type":["string","null"]},"deviation":{"type":"integer","format":"int32"},"displayName":{"type":["string","null"]},"draws":{"type":"integer","format":"int64"},"games":{"type":"integer","format":"int32"},"latestAt":{"type":["string","null"],"format":"date-time"},"losses":{"type":"integer","format":"int64"},"player":{"type":"string"},"rank":{"type":"integer","format":"int64"},"rating":{"type":"integer","format":"int32"},"ratingProgress":{"type":"integer","format":"int32"},"wins":{"type":"integer","format":"int64"}}},"chess_RatingLeaderboardResponse":{"type":"object","required":["perfKey","page","limit","activeWithinDays","hasMore","items"],"properties":{"activeWithinDays":{"type":"integer","format":"int64"},"countryCode":{"type":["string","null"]},"hasMore":{"type":"boolean"},"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_RatingLeaderboardPlayerResponse"}},"limit":{"type":"integer","format":"int64"},"page":{"type":"integer","format":"int64"},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"}}},"chess_RatingLeaderboardRulesResponse":{"type":"object","required":["initialRating","minimumRating","maximumRating","minimumGames","maximumDeviationExclusive","activeWithinDays","supportedPerfs"],"properties":{"activeWithinDays":{"type":"integer","format":"int64"},"initialRating":{"type":"integer","format":"int32"},"maximumDeviationExclusive":{"type":"integer","format":"int32"},"maximumRating":{"type":"integer","format":"int32"},"minimumGames":{"type":"integer","format":"int32"},"minimumRating":{"type":"integer","format":"int32"},"supportedPerfs":{"type":"array","items":{"$ref":"#/components/schemas/chess_PerfKey"}}}},"chess_RatingOnboardingResponse":{"type":"object","required":["player","skillLevel","initialRating","locked"],"properties":{"initialRating":{"type":"integer","format":"int32"},"locked":{"type":"boolean"},"player":{"type":"string"},"skillLevel":{"$ref":"#/components/schemas/chess_RatingSkillLevel"}}},"chess_RatingPoolStatsResponse":{"type":"object","required":["perfKey","playerCount","liveGames","livePlayers"],"properties":{"averageRating":{"type":["number","null"],"format":"double"},"countryCode":{"type":["string","null"]},"liveGames":{"type":"integer","format":"int64"},"livePlayers":{"type":"integer","format":"int64"},"medianRating":{"type":["number","null"],"format":"double"},"perfKey":{"$ref":"#/components/schemas/chess_PerfKey"},"playerCount":{"type":"integer","format":"int64"}}},"chess_RatingRecordResponse":{"type":"object","required":["wins","draws","losses"],"properties":{"draws":{"type":"integer","format":"int64"},"losses":{"type":"integer","format":"int64"},"wins":{"type":"integer","format":"int64"}}},"chess_RatingSkillLevel":{"type":"string","enum":["new","beginner","intermediate","advanced"]},"chess_ReadinessStatus":{"type":"object","required":["status","service","database","broker"],"properties":{"broker":{"type":"boolean"},"database":{"type":"boolean"},"service":{"type":"string"},"status":{"type":"string"}}},"chess_RequestComputerHintRequest":{"type":"object","required":["player","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"}}},"chess_RequestDraughtsAnalysisRequest":{"type":"object","required":["player"],"properties":{"idempotencyKey":{"type":["string","null"]},"player":{"type":"string"},"premium":{"type":"boolean"}}},"chess_RequestDraughtsComputerHintRequest":{"type":"object","required":["player","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"}}},"chess_RequestMatchAnalysisRequest":{"type":"object","required":["player"],"properties":{"idempotencyKey":{"type":["string","null"],"description":"Required for premium requests so retries cannot consume two credits."},"player":{"type":"string"},"premium":{"type":"boolean","description":"Re-run the report at a higher Stockfish depth. This consumes one\n`premium_review` credit; standard analysis remains free and compatible."}}},"chess_ResolveFairPlayReviewRequest":{"type":"object","required":["action","reviewer","note"],"properties":{"action":{"$ref":"#/components/schemas/chess_FairPlayResolution"},"note":{"type":"string"},"reviewer":{"type":"string"}}},"chess_SetMatchNoteRequest":{"type":"object","required":["text"],"properties":{"player":{"type":["string","null"],"description":"Optional note owner identity. In production the trusted\n`x-wallet-address` header becomes authoritative when present."},"text":{"type":"string","description":"Private note text. Empty/whitespace clears the note."}}},"chess_Side":{"type":"string","enum":["white","black"]},"chess_StartArenaRequest":{"type":"object","required":["organizer"],"properties":{"organizer":{"type":"string"}}},"chess_StartNextRoundRequest":{"type":"object","required":["organizer"],"properties":{"manualPairings":{"type":["string","null"]},"organizer":{"type":"string"}}},"chess_SwissBetResponse":{"type":"object","required":["id","swissId","bettor","predictedPlayerId","stakeUsdc","status","payoutUsdc","createdAt"],"properties":{"bettor":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"payoutUsdc":{"type":"string"},"predictedPlayerId":{"type":"string"},"stakeUsdc":{"type":"string"},"status":{"type":"string"},"swissId":{"type":"string"}}},"chess_SwissFormat":{"type":"string","enum":["swiss","champions"]},"chess_SwissGameKind":{"type":"string","enum":["chess","draughts"]},"chess_SwissListResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_SwissSummaryResponse"}}}},"chess_SwissMarketOddsResponse":{"type":"object","required":["swissId","status","totalPoolUsdc","rakeBps","outcomes"],"properties":{"outcomes":{"type":"array","items":{"$ref":"#/components/schemas/chess_SwissOutcomePoolResponse"}},"rakeBps":{"type":"integer","format":"int32"},"status":{"type":"string"},"swissId":{"type":"string"},"totalPoolUsdc":{"type":"string"},"voidReason":{"type":["string","null"]},"winningPlayerId":{"type":["string","null"]}}},"chess_SwissOutcomePoolResponse":{"type":"object","required":["playerId","playerName","poolUsdc"],"properties":{"decimalOdds":{"type":["string","null"]},"playerId":{"type":"string"},"playerName":{"type":"string"},"poolUsdc":{"type":"string"}}},"chess_SwissPairingResponse":{"type":"object","required":["round","board","game","status","isForfeit","stage","stageRound","leg","armageddon"],"properties":{"armageddon":{"type":"boolean"},"black":{"type":["string","null"]},"blackSeed":{"type":["integer","null"],"format":"int32"},"board":{"type":"integer","format":"int32"},"game":{"$ref":"#/components/schemas/chess_SwissGameKind"},"isForfeit":{"type":"boolean"},"leg":{"type":"integer","format":"int32"},"matchId":{"type":["string","null"]},"result":{"type":["string","null"]},"round":{"type":"integer","format":"int32"},"stage":{"type":"string"},"stageRound":{"type":"integer","format":"int32"},"status":{"$ref":"#/components/schemas/chess_SwissPairingStatus"},"tieNumber":{"type":["integer","null"],"format":"int32"},"white":{"type":["string","null"]},"whiteSeed":{"type":["integer","null"],"format":"int32"}}},"chess_SwissPairingStatus":{"type":"string","enum":["bye","ongoing","white","black","draw"]},"chess_SwissPhase":{"type":"string","enum":["registration","league","playoff","knockout","finished"]},"chess_SwissPlayerRequest":{"type":"object","required":["name"],"properties":{"forfeit":{"type":"boolean"},"name":{"type":"string"},"walletAddress":{"type":["string","null"]}}},"chess_SwissPrizePolicy":{"type":"string","enum":["standard","highStakes"]},"chess_SwissResponse":{"allOf":[{"$ref":"#/components/schemas/chess_SwissSummaryResponse"},{"type":"object","required":["standings","rounds","standingsTotal","standingsOffset","standingsHasMore","pairingsTotal","pairingsOffset","pairingsHasMore"],"properties":{"myPairing":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_SwissPairingResponse"}]},"pairingsHasMore":{"type":"boolean"},"pairingsOffset":{"type":"integer","minimum":0},"pairingsTotal":{"type":"integer","minimum":0},"rounds":{"type":"array","items":{"$ref":"#/components/schemas/chess_SwissRoundResponse"}},"standings":{"type":"array","items":{"$ref":"#/components/schemas/chess_SwissStandingResponse"}},"standingsHasMore":{"type":"boolean"},"standingsOffset":{"type":"integer","minimum":0},"standingsTotal":{"type":"integer","minimum":0}}}]},"chess_SwissRoundResponse":{"type":"object","required":["round","pairings"],"properties":{"pairings":{"type":"array","items":{"$ref":"#/components/schemas/chess_SwissPairingResponse"}},"round":{"type":"integer","format":"int32"}}},"chess_SwissStandingResponse":{"type":"object","required":["rank","name","points","tieBreak","directEncounter","buchholzCutOne","sonnebornBerger","wins","draws","losses","byes","absent"],"properties":{"absent":{"type":"boolean"},"buchholzCutOne":{"type":"number","format":"float"},"byes":{"type":"integer","format":"int32"},"directEncounter":{"type":"number","format":"float"},"draws":{"type":"integer","format":"int32"},"losses":{"type":"integer","format":"int32"},"name":{"type":"string"},"performance":{"type":["number","null"],"format":"float"},"points":{"type":"number","format":"float"},"rank":{"type":"integer","format":"int32"},"sonnebornBerger":{"type":"number","format":"float"},"tieBreak":{"type":"number","format":"float"},"wins":{"type":"integer","format":"int32"}}},"chess_SwissStatus":{"type":"string","enum":["created","started","finished"]},"chess_SwissSummaryResponse":{"type":"object","required":["id","name","organizer","game","status","round","nbRounds","participantCount","ongoingCount","timeControl","entryFeeUsdc","maxPlayers","prizePolicy","prizePoolBps","platformShareBps","minimumPlayers","createdAt","format","phase","leagueRounds","bracketSize","directQualifiers","playoffPlayers","eliminatedPlayers","knockoutRound","knockoutGamesPerTie"],"properties":{"bracketSize":{"type":"integer","format":"int32"},"createdAt":{"type":"string","format":"date-time"},"directQualifiers":{"type":"integer","format":"int32"},"draughtsVariant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.DraughtsVariant"}]},"eliminatedPlayers":{"type":"integer","format":"int32"},"entryFeeUsdc":{"type":"string"},"finishedAt":{"type":["string","null"],"format":"date-time"},"format":{"$ref":"#/components/schemas/chess_SwissFormat"},"game":{"$ref":"#/components/schemas/chess_SwissGameKind"},"id":{"type":"string"},"knockoutGamesPerTie":{"type":"integer","format":"int32"},"knockoutRound":{"type":"integer","format":"int32"},"leagueRounds":{"type":"integer","format":"int32"},"maxPlayers":{"type":"integer","format":"int32"},"minimumPlayers":{"type":"integer","format":"int32"},"name":{"type":"string"},"nbRounds":{"type":"integer","format":"int32"},"ongoingCount":{"type":"integer","format":"int32"},"organizer":{"type":"string"},"participantCount":{"type":"integer","format":"int32"},"phase":{"$ref":"#/components/schemas/chess_SwissPhase"},"platformShareBps":{"type":"integer","format":"int32"},"playoffPlayers":{"type":"integer","format":"int32"},"prizePolicy":{"$ref":"#/components/schemas/chess_SwissPrizePolicy"},"prizePoolBps":{"type":"integer","format":"int32"},"round":{"type":"integer","format":"int32"},"startedAt":{"type":["string","null"],"format":"date-time"},"startingFen":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/chess_SwissStatus"},"timeControl":{"$ref":"#/components/schemas/chess_TimeControl"},"winner":{"type":["string","null"]}}},"chess_TimeControl":{"type":"object","required":["mode","initialSeconds","incrementSeconds"],"properties":{"incrementSeconds":{"type":"integer","format":"int32"},"initialSeconds":{"type":"integer","format":"int32"},"mode":{"$ref":"#/components/schemas/chess_ClockMode"}}},"chess_UpdateCoachProfileRequest":{"type":"object","required":["experience","onboardingComplete","preferredMode"],"properties":{"experience":{"$ref":"#/components/schemas/chess_CoachExperience"},"onboardingComplete":{"type":"boolean"},"preferredMode":{"$ref":"#/components/schemas/chess_CoachPreferredMode"}}},"chess_UpdateDraughtsCoachProgressRequest":{"type":"object","required":["skillKey"],"properties":{"matchId":{"type":["string","null"]},"ply":{"type":["integer","null"],"format":"int32"},"skillKey":{"type":"string"},"success":{"type":"boolean"}}},"chess_UpdateRatingOnboardingRequest":{"type":"object","required":["skillLevel"],"properties":{"skillLevel":{"$ref":"#/components/schemas/chess_RatingSkillLevel"}}},"chess_UpsertCoachProgressRequest":{"type":"object","required":["lesson_key","chapter_key","score","completed"],"properties":{"chapter_key":{"type":"string"},"completed":{"type":"boolean"},"lesson_key":{"type":"string"},"score":{"type":"integer","format":"int32"}}},"chess_UpsertMatchCommentRequest":{"type":"object","required":["ply","text"],"properties":{"player":{"type":["string","null"],"description":"Optional author identity. In production the trusted\n`x-wallet-address` header becomes authoritative when present."},"ply":{"type":"integer","format":"int32","description":"Linear move index in the match. `0` is the starting position."},"text":{"type":"string","description":"Shared position comment text. Empty text is rejected; use DELETE to\nremove a comment."}}},"chess_WeaknessProfileResponse":{"type":"object","required":["player","generatedAt","totalMistakes","openings","phases","sides","timeControls","motifs"],"properties":{"generatedAt":{"type":"string","format":"date-time"},"motifs":{"type":"array","items":{"$ref":"#/components/schemas/chess_InsightBucketResponse"}},"openings":{"type":"array","items":{"$ref":"#/components/schemas/chess_InsightBucketResponse"}},"phases":{"type":"array","items":{"$ref":"#/components/schemas/chess_InsightBucketResponse"}},"player":{"type":"string"},"sides":{"type":"array","items":{"$ref":"#/components/schemas/chess_InsightBucketResponse"}},"timeControls":{"type":"array","items":{"$ref":"#/components/schemas/chess_InsightBucketResponse"}},"totalMistakes":{"type":"integer","format":"int32"}}},"chess_WithdrawalResponse":{"type":"object","required":["id","player","toAddress","amountUsdc","feeUsdc","netAmountUsdc","status"],"properties":{"amountUsdc":{"type":"string"},"feeUsdc":{"type":"string"},"id":{"type":"string"},"netAmountUsdc":{"type":"string"},"player":{"type":"string"},"sentAt":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"toAddress":{"type":"string"},"txHash":{"type":["string","null"]}}},"chess_draughts.Clocks":{"type":"object","required":["whiteMs","blackMs"],"properties":{"blackMs":{"type":"integer","format":"int64"},"whiteMs":{"type":"integer","format":"int64"}}},"chess_draughts.CoachCatalogResponse":{"type":"object","required":["version","maximumPoints","sections"],"properties":{"maximumPoints":{"type":"integer","format":"int32"},"sections":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.CoachSectionResponse"}},"version":{"type":"integer","format":"int32"}}},"chess_draughts.CoachChapterResponse":{"type":"object","required":["key","title","instruction","variant","fen","side","targetUci","hints","successMessage"],"properties":{"fen":{"type":"string"},"hints":{"type":"array","items":{"type":"string"}},"instruction":{"type":"string"},"key":{"type":"string"},"side":{"type":"string"},"successMessage":{"type":"string"},"targetUci":{"type":"string"},"title":{"type":"string"},"variant":{"$ref":"#/components/schemas/chess_draughts.DraughtsVariant"}}},"chess_draughts.CoachExperience":{"type":"string","enum":["beginner","intermediate","advanced"]},"chess_draughts.CoachGameSummaryResponse":{"type":"object","required":["outcome","totalPlies","playerMoves","reviewedMoves","moveQuality","help","message"],"properties":{"finishedAt":{"type":["string","null"],"format":"date-time"},"help":{"$ref":"#/components/schemas/chess_draughts.CoachHelpStatsResponse"},"message":{"type":"string"},"moveQuality":{"$ref":"#/components/schemas/chess_draughts.CoachMoveQualityResponse"},"outcome":{"$ref":"#/components/schemas/chess_draughts.CoachOutcome"},"playerMoves":{"type":"integer","format":"int32"},"resultReason":{"type":["string","null"]},"reviewedMoves":{"type":"integer","format":"int32"},"totalPlies":{"type":"integer","format":"int32"}}},"chess_draughts.CoachHelpStatsResponse":{"type":"object","required":["hints","undos","usedHelp"],"properties":{"hints":{"type":"integer","format":"int32"},"undos":{"type":"integer","format":"int32"},"usedHelp":{"type":"boolean"}}},"chess_draughts.CoachHintRequest":{"type":"object","required":["player","idempotencyKey"],"properties":{"expectedPly":{"type":["integer","null"],"format":"int32"},"idempotencyKey":{"type":"string"},"player":{"type":"string"}}},"chess_draughts.CoachHintResponse":{"type":"object","required":["id","matchId","ply","level","message","motif","actions","createdAt"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"level":{"type":"integer","format":"int32"},"matchId":{"type":"string"},"message":{"type":"string"},"motif":{"$ref":"#/components/schemas/chess_draughts.CoachMotif"},"ply":{"type":"integer","format":"int32"},"suggestedSan":{"type":["string","null"]},"suggestedUci":{"type":["string","null"]}}},"chess_draughts.CoachHomeResponse":{"type":"object","required":["profile","earnedPoints","maximumPoints","trainingPositionCount","lessons"],"properties":{"earnedPoints":{"type":"integer","format":"int32"},"lessons":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.CoachLessonStatusResponse"}},"maximumPoints":{"type":"integer","format":"int32"},"profile":{"$ref":"#/components/schemas/chess_draughts.CoachProfileResponse"},"recommendedLessonKey":{"type":["string","null"]},"trainingPositionCount":{"type":"integer","format":"int32"}}},"chess_draughts.CoachLessonAttemptRequest":{"type":"object","required":["player","uci","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"},"uci":{"type":"string"}}},"chess_draughts.CoachLessonAttemptResponse":{"type":"object","required":["id","player","lessonKey","chapterKey","attemptedUci","legal","correct","score","message","attempts","bestScore","completed","createdAt"],"properties":{"attemptedUci":{"type":"string"},"attempts":{"type":"integer","format":"int32"},"bestScore":{"type":"integer","format":"int32"},"chapterKey":{"type":"string"},"completed":{"type":"boolean"},"correct":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"legal":{"type":"boolean"},"lessonKey":{"type":"string"},"message":{"type":"string"},"nextHint":{"type":["string","null"]},"player":{"type":"string"},"score":{"type":"integer","format":"int32"}}},"chess_draughts.CoachLessonResponse":{"type":"object","required":["key","title","summary","difficulty","maximumPoints","prerequisiteLessonKeys","chapters"],"properties":{"chapters":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.CoachChapterResponse"}},"difficulty":{"type":"integer","format":"int32"},"key":{"type":"string"},"maximumPoints":{"type":"integer","format":"int32"},"prerequisiteLessonKeys":{"type":"array","items":{"type":"string"}},"summary":{"type":"string"},"title":{"type":"string"}}},"chess_draughts.CoachLessonStatus":{"type":"string","enum":["locked","available","inProgress","completed"]},"chess_draughts.CoachLessonStatusResponse":{"type":"object","required":["lessonKey","status","earnedPoints","maximumPoints","completedChapters","totalChapters"],"properties":{"completedChapters":{"type":"integer","format":"int32"},"earnedPoints":{"type":"integer","format":"int32"},"lessonKey":{"type":"string"},"maximumPoints":{"type":"integer","format":"int32"},"status":{"$ref":"#/components/schemas/chess_draughts.CoachLessonStatus"},"totalChapters":{"type":"integer","format":"int32"}}},"chess_draughts.CoachMotif":{"type":"string","enum":["captureSequence","promotion","materialLoss","tacticalMiss","positionalPlay"]},"chess_draughts.CoachMoveAttemptRequest":{"type":"object","required":["player","uci","idempotencyKey"],"properties":{"expectedPly":{"type":["integer","null"],"format":"int32"},"idempotencyKey":{"type":"string"},"player":{"type":"string"},"uci":{"type":"string"}}},"chess_draughts.CoachMoveAttemptResponse":{"type":"object","required":["attemptId","matchId","ply","status","classification","motif","attemptedUci","attemptedSan","message","canUndo","canContinue","actions","createdAt"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"attemptId":{"type":"string"},"attemptedSan":{"type":"string"},"attemptedUci":{"type":"string"},"bestSan":{"type":["string","null"]},"bestUci":{"type":["string","null"]},"canContinue":{"type":"boolean"},"canUndo":{"type":"boolean"},"classification":{"$ref":"#/components/schemas/chess_AnalysisClassification"},"createdAt":{"type":"string","format":"date-time"},"loss":{"type":["integer","null"],"format":"int32"},"matchId":{"type":"string"},"matchState":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}]},"message":{"type":"string"},"motif":{"$ref":"#/components/schemas/chess_draughts.CoachMotif"},"ply":{"type":"integer","format":"int32"},"principalVariation":{"type":["string","null"]},"scoreAfter":{"type":["integer","null"],"format":"int32"},"scoreBefore":{"type":["integer","null"],"format":"int32"},"status":{"$ref":"#/components/schemas/chess_draughts.CoachMoveStatus"}}},"chess_draughts.CoachMoveQualityResponse":{"type":"object","required":["best","good","inaccuracies","mistakes","blunders"],"properties":{"averageLoss":{"type":["number","null"],"format":"double"},"best":{"type":"integer","format":"int32"},"blunders":{"type":"integer","format":"int32"},"good":{"type":"integer","format":"int32"},"inaccuracies":{"type":"integer","format":"int32"},"mistakes":{"type":"integer","format":"int32"}}},"chess_draughts.CoachMoveStatus":{"type":"string","enum":["review","continued","undone","stale"]},"chess_draughts.CoachOutcome":{"type":"string","enum":["win","draw","loss","unresolved"]},"chess_draughts.CoachPreferredMode":{"type":"string","enum":["learn","play","train","lessons"]},"chess_draughts.CoachProfileResponse":{"type":"object","required":["player","experience","onboardingComplete","preferredMode","createdAt","updatedAt"],"properties":{"createdAt":{"type":"string","format":"date-time"},"experience":{"$ref":"#/components/schemas/chess_draughts.CoachExperience"},"onboardingComplete":{"type":"boolean"},"player":{"type":"string"},"preferredMode":{"$ref":"#/components/schemas/chess_draughts.CoachPreferredMode"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_draughts.CoachReviewActionRequest":{"type":"object","required":["player","attemptId"],"properties":{"attemptId":{"type":"string"},"expectedPly":{"type":["integer","null"],"format":"int32"},"player":{"type":"string"}}},"chess_draughts.CoachSectionResponse":{"type":"object","required":["key","title","summary","lessons"],"properties":{"key":{"type":"string"},"lessons":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.CoachLessonResponse"}},"summary":{"type":"string"},"title":{"type":"string"}}},"chess_draughts.CoachStateQuery":{"type":"object","required":["player"],"properties":{"player":{"type":"string"}}},"chess_draughts.CoachStateResponse":{"type":"object","required":["matchId","enabled","player","ply","canMove","awaitingResponse","hintLevel","actions"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"awaitingResponse":{"type":"boolean"},"canMove":{"type":"boolean"},"enabled":{"type":"boolean"},"hintLevel":{"type":"integer","format":"int32"},"matchId":{"type":"string"},"pendingReview":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.CoachMoveAttemptResponse"}]},"player":{"type":"string"},"ply":{"type":"integer","format":"int32"},"summary":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.CoachGameSummaryResponse"}]}}},"chess_draughts.CoachTrainingAttemptRequest":{"type":"object","required":["uci","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"uci":{"type":"string"}}},"chess_draughts.CoachTrainingAttemptResponse":{"type":"object","required":["id","player","matchId","sourcePly","attemptedUci","legal","correct","attempts","hintLevel","message","actions","createdAt"],"properties":{"actions":{"type":"array","items":{"$ref":"#/components/schemas/chess_CoachUiAction"}},"attemptedUci":{"type":"string"},"attempts":{"type":"integer","format":"int32"},"correct":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"hintLevel":{"type":"integer","format":"int32"},"id":{"type":"string"},"legal":{"type":"boolean"},"matchId":{"type":"string"},"message":{"type":"string"},"player":{"type":"string"},"sourcePly":{"type":"integer","format":"int32"},"suggestedUci":{"type":["string","null"]}}},"chess_draughts.CoachTrainingItemResponse":{"type":"object","required":["matchId","ply","side","phase","motif","classification","variant","fen","createdAt"],"properties":{"bestUci":{"type":["string","null"]},"classification":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"fen":{"type":"string"},"loss":{"type":["integer","null"],"format":"int32"},"matchId":{"type":"string"},"motif":{"type":"string"},"phase":{"type":"string"},"playedUci":{"type":["string","null"]},"ply":{"type":"integer","format":"int32"},"principalVariation":{"type":["string","null"]},"side":{"type":"string"},"variant":{"type":"string"}}},"chess_draughts.CoachTrainingQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"}}},"chess_draughts.CoachTrainingResponse":{"type":"object","required":["player","items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.CoachTrainingItemResponse"}},"player":{"type":"string"}}},"chess_draughts.ColorChoice":{"type":"string","enum":["white","black","random"]},"chess_draughts.CreateMatchChatMessageRequest":{"type":"object","required":["room","text"],"properties":{"author":{"type":["string","null"]},"room":{"$ref":"#/components/schemas/chess_draughts.MatchChatRoom"},"text":{"type":"string"}}},"chess_draughts.CreateMatchRequest":{"type":"object","required":["creator"],"properties":{"allow_time_extensions":{"type":"boolean","description":"Allows either participant to spend one extension credit to add the same\namount to both clocks. Only available for unstaked PvP games."},"color":{"$ref":"#/components/schemas/chess_draughts.ColorChoice"},"creator":{"type":"string"},"increment_seconds":{"type":["integer","null"],"format":"int64"},"initial_seconds":{"type":["integer","null"],"format":"int64"},"rated":{"type":"boolean"},"stake_usdc":{"type":["string","null"]},"starting_fen":{"type":["string","null"]},"variant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.DraughtsVariant"}]}}},"chess_draughts.DeleteMatchCommentRequest":{"type":"object","properties":{"player":{"type":["string","null"]}}},"chess_draughts.DraughtsVariant":{"type":"string","enum":["standard","frisian","frysk","antidraughts","breakthrough","russian","brazilian","from_position"]},"chess_draughts.DrawResponseRequest":{"type":"object","required":["player","accept"],"properties":{"accept":{"type":"boolean"},"player":{"type":"string"}}},"chess_draughts.ExtendMatchTimeRequest":{"type":"object","required":["player","seconds","idempotencyKey"],"properties":{"idempotencyKey":{"type":"string"},"player":{"type":"string"},"seconds":{"type":"integer","format":"int32"}}},"chess_draughts.GameResult":{"type":"string","enum":["white","black","draw"]},"chess_draughts.JoinMatchRequest":{"type":"object","required":["player"],"properties":{"player":{"type":"string"}}},"chess_draughts.MakeMoveRequest":{"type":"object","required":["player","uci"],"properties":{"player":{"type":"string"},"uci":{"type":"string"}}},"chess_draughts.MatchChatMessageResponse":{"type":"object","required":["id","matchId","room","author","text","createdAt"],"properties":{"author":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int64"},"matchId":{"type":"string"},"room":{"$ref":"#/components/schemas/chess_draughts.MatchChatRoom"},"text":{"type":"string"}}},"chess_draughts.MatchChatMessagesResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.MatchChatMessageResponse"}}}},"chess_draughts.MatchChatQuery":{"type":"object","properties":{"limit":{"type":["integer","null"],"format":"int64"},"player":{"type":["string","null"]},"room":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.MatchChatRoom"}]}}},"chess_draughts.MatchChatRoom":{"type":"string","enum":["player","spectator"]},"chess_draughts.MatchCommentResponse":{"type":"object","required":["id","matchId","ply","fen","author","text","createdAt","updatedAt"],"properties":{"author":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"fen":{"type":"string"},"id":{"type":"string"},"matchId":{"type":"string"},"ply":{"type":"integer","format":"int32"},"text":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}}},"chess_draughts.MatchCommentsQuery":{"type":"object","properties":{"ply":{"type":["integer","null"],"format":"int32"}}},"chess_draughts.MatchCommentsResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.MatchCommentResponse"}}}},"chess_draughts.MatchListResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"}}}},"chess_draughts.MatchNoteQuery":{"type":"object","properties":{"player":{"type":["string","null"]}}},"chess_draughts.MatchNoteResponse":{"type":"object","required":["matchId","player","text"],"properties":{"createdAt":{"type":["string","null"],"format":"date-time"},"matchId":{"type":"string"},"player":{"type":"string"},"text":{"type":"string"},"updatedAt":{"type":["string","null"],"format":"date-time"}}},"chess_draughts.MatchRematchStateResponse":{"type":"object","properties":{"nextMatchId":{"type":["string","null"]},"offeredBy":{"type":["string","null"]}}},"chess_draughts.MatchResponse":{"type":"object","required":["id","inviteCode","liveTopic","variant","startingFen","status","fen","turn","ply","timeControl","clocks","timeExtensions","clockUpdatedAt","takeback","rematch","rating","createdAt"],"properties":{"black":{"type":["string","null"]},"clockUpdatedAt":{"type":"string","format":"date-time"},"clocks":{"$ref":"#/components/schemas/chess_draughts.Clocks"},"computer":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_DraughtsComputerOpponentResponse"}]},"createdAt":{"type":"string","format":"date-time"},"drawOfferBy":{"type":["string","null"]},"fen":{"type":"string"},"finishedAt":{"type":["string","null"],"format":"date-time"},"id":{"type":"string"},"inviteCode":{"type":"string"},"liveTopic":{"type":"string"},"loser":{"type":["string","null"]},"ply":{"type":"integer","format":"int32"},"rating":{"$ref":"#/components/schemas/chess_MatchRatingResponse"},"rematch":{"$ref":"#/components/schemas/chess_draughts.MatchRematchStateResponse"},"result":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.GameResult"}]},"resultReason":{"type":["string","null"]},"startedAt":{"type":["string","null"],"format":"date-time"},"startingFen":{"type":"string"},"status":{"$ref":"#/components/schemas/chess_draughts.MatchStatus"},"takeback":{"$ref":"#/components/schemas/chess_draughts.MatchTakebackStateResponse"},"timeControl":{"$ref":"#/components/schemas/chess_draughts.TimeControl"},"timeExtensions":{"$ref":"#/components/schemas/chess_draughts.MatchTimeExtensionStateResponse"},"turn":{"$ref":"#/components/schemas/chess_draughts.Side"},"variant":{"$ref":"#/components/schemas/chess_draughts.DraughtsVariant"},"wager":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/chess_draughts.MatchWagerResponse"}]},"white":{"type":["string","null"]},"winner":{"type":["string","null"]}}},"chess_draughts.MatchStatus":{"type":"string","enum":["waiting","active","finished","aborted"]},"chess_draughts.MatchTakebackStateResponse":{"type":"object","required":["white","black","takebackable"],"properties":{"black":{"type":"boolean"},"takebackable":{"type":"boolean"},"white":{"type":"boolean"}}},"chess_draughts.MatchTimeExtensionStateResponse":{"type":"object","required":["allowed","used","totalSeconds","maxUses","maxTotalSeconds"],"properties":{"allowed":{"type":"boolean"},"maxTotalSeconds":{"type":"integer","format":"int32"},"maxUses":{"type":"integer","format":"int32"},"totalSeconds":{"type":"integer","format":"int32"},"used":{"type":"integer","format":"int32"}}},"chess_draughts.MatchWagerResponse":{"type":"object","required":["stakeUsdc","feeBps","creatorPlayer","creatorLocked","opponentLocked","status"],"properties":{"creatorLocked":{"type":"boolean"},"creatorPlayer":{"type":"string"},"feeBps":{"type":"integer","format":"int32"},"opponentLocked":{"type":"boolean"},"opponentPlayer":{"type":["string","null"]},"settledAt":{"type":["string","null"],"format":"date-time"},"stakeUsdc":{"type":"string"},"status":{"type":"string"},"winnerPlayer":{"type":["string","null"]}}},"chess_draughts.MoveResponse":{"type":"object","required":["ply","uci","san","fenAfter","byPlayer","createdAt"],"properties":{"byPlayer":{"type":"string"},"clockMsRemaining":{"type":["integer","null"],"format":"int64"},"createdAt":{"type":"string","format":"date-time"},"fenAfter":{"type":"string"},"ply":{"type":"integer","format":"int32"},"san":{"type":"string"},"uci":{"type":"string"}}},"chess_draughts.MoveResultResponse":{"type":"object","required":["match","move"],"properties":{"match":{"$ref":"#/components/schemas/chess_draughts.MatchResponse"},"move":{"$ref":"#/components/schemas/chess_draughts.MoveResponse"}}},"chess_draughts.MovesResponse":{"type":"object","required":["moves"],"properties":{"moves":{"type":"array","items":{"$ref":"#/components/schemas/chess_draughts.MoveResponse"}}}},"chess_draughts.PdnResponse":{"type":"object","required":["pdn"],"properties":{"pdn":{"type":"string"}}},"chess_draughts.PlayerActionRequest":{"type":"object","required":["player"],"properties":{"player":{"type":"string"}}},"chess_draughts.SetMatchNoteRequest":{"type":"object","required":["text"],"properties":{"player":{"type":["string","null"]},"text":{"type":"string"}}},"chess_draughts.Side":{"type":"string","enum":["white","black"]},"chess_draughts.TimeControl":{"type":"object","required":["mode","initialSeconds","incrementSeconds"],"properties":{"incrementSeconds":{"type":"integer","format":"int32"},"initialSeconds":{"type":"integer","format":"int32"},"mode":{"$ref":"#/components/schemas/chess_ClockMode"}}},"chess_draughts.UpdateCoachProfileRequest":{"type":"object","required":["experience","onboardingComplete","preferredMode"],"properties":{"experience":{"$ref":"#/components/schemas/chess_draughts.CoachExperience"},"onboardingComplete":{"type":"boolean"},"preferredMode":{"$ref":"#/components/schemas/chess_draughts.CoachPreferredMode"}}},"chess_draughts.UpsertMatchCommentRequest":{"type":"object","required":["ply","text"],"properties":{"player":{"type":["string","null"]},"ply":{"type":"integer","format":"int32"},"text":{"type":"string"}}},"gas-sponsor_AuthContract":{"type":"object","required":["transport","verificationConfigured","verificationImplemented","note"],"properties":{"note":{"type":"string"},"transport":{"type":"array","items":{"type":"string"}},"verificationConfigured":{"type":"boolean"},"verificationImplemented":{"type":"boolean"}}},"gas-sponsor_BackingStores":{"type":"object","required":["databaseUrlPresent","redisUrlPresent","rabbitmqConfigured"],"properties":{"databaseUrlPresent":{"type":"boolean"},"rabbitmqConfigured":{"type":"boolean"},"redisUrlPresent":{"type":"boolean"}}},"gas-sponsor_CapabilitiesResponse":{"type":"object","required":["auth","solana","stores"],"properties":{"auth":{"$ref":"#/components/schemas/gas-sponsor_AuthContract"},"solana":{"$ref":"#/components/schemas/gas-sponsor_SolanaCapabilities"},"stores":{"$ref":"#/components/schemas/gas-sponsor_BackingStores"}}},"gas-sponsor_HealthStatus":{"type":"object","required":["status","service","uptimeSeconds"],"properties":{"service":{"type":"string"},"status":{"type":"string"},"uptimeSeconds":{"type":"integer","format":"int64","minimum":0}}},"gas-sponsor_SolanaCapabilities":{"type":"object","required":["previewOnly","configured","signer","sponsorRpcUrl","sponsorshipPath","requiresPrivyAuth","defaultPrefundRent"],"properties":{"configured":{"type":"boolean"},"defaultPrefundRent":{"type":"boolean"},"previewOnly":{"type":"boolean"},"requiresPrivyAuth":{"type":"boolean"},"signer":{"type":"string"},"sponsorPublicKey":{"type":["string","null"]},"sponsorRpcUrl":{"type":"string"},"sponsorshipPath":{"type":"string"}}},"gas-sponsor_SolanaSponsorRequest":{"type":"object","required":["serializedTransaction"],"properties":{"prefundRent":{"type":["boolean","null"]},"serializedTransaction":{"type":"string"}}},"gas-sponsor_SolanaSponsorResponse":{"type":"object","required":["previewOnly","configured","signer","sponsorPublicKey","serializedTransactionBytes","sponsoredSerializedTransaction","prefundRent","note"],"properties":{"configured":{"type":"boolean"},"note":{"type":"string"},"prefundRent":{"type":"boolean"},"previewOnly":{"type":"boolean"},"serializedTransactionBytes":{"type":"integer","minimum":0},"signer":{"type":"string"},"sponsorPublicKey":{"type":"string"},"sponsoredSerializedTransaction":{"type":"string"},"submittedSignature":{"type":["string","null"]}}},"earn_ApiResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean"},"data":{},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}}}},"kash_UsernameAvailabilityResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"username":{"type":"string","description":"Normalized (lower-case, trimmed)"},"available":{"type":"boolean"},"reason":{"type":"string","description":"Why not, when unavailable"}}}}},"kash_ProfileResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"wallet":{"type":"string"},"username":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}}}},"kash_ReferralClaimResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"referrerWallet":{"type":"string"},"code":{"type":"string"},"claimedAt":{"type":"string","format":"date-time"}}}}},"kash_ReferralStatsResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"wallet":{"type":"string"},"username":{"type":"string","nullable":true},"referred":{"type":"integer","description":"Referees who have deposited"},"pending":{"type":"integer","description":"Referees who claimed but have not deposited yet"}}}}},"kash_PurchaseRequest":{"type":"object","required":["wallet","usdcAmount"],"properties":{"wallet":{"type":"string","example":"0x1111111111111111111111111111111111111111"},"usdcAmount":{"type":"string","description":"Decimal string","example":"10"},"paymentTxHash":{"type":"string","description":"On-chain USDC payment tx to the treasury wallet — REQUIRED in real-USDC mode; verified and usable exactly once."}}},"kash_Purchase":{"type":"object","properties":{"id":{"type":"string"},"wallet":{"type":"string"},"usdcPaid":{"type":"string","example":"10"},"kashReceived":{"type":"string","example":"10000"},"kashPriceUsd":{"type":"string","example":"0.001"},"createdAt":{"type":"string","format":"date-time"},"mintTxHash":{"type":"string","description":"Token mint tx (mock or real)."}}},"kash_PurchaseResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/kash_Purchase"}}},"kash_ActivityRequest":{"type":"object","required":["wallet","type","notionalUsd"],"properties":{"wallet":{"type":"string"},"type":{"type":"string","enum":["buy","sell","trade"]},"notionalUsd":{"type":"string","description":"Decimal string","example":"100"},"ref":{"type":"string","description":"Optional ledger reference"}}},"kash_Accrual":{"type":"object","properties":{"applied":{"type":"boolean"},"reason":{"type":"string","enum":["locked","duplicate","epoch_usd_budget","epoch_kash_cap","allocation_exhausted","dust"],"description":"Why no reward was granted (present when applied=false)."},"wallet":{"type":"string"},"type":{"type":"string"},"notionalUsd":{"type":"string","example":"100"},"feeUsd":{"type":"string","example":"0.3"},"points":{"type":"string","example":"12.5"},"pointsBreakdown":{"type":"array","description":"Audit: the subscription tier and flat revenue share applied (always exactly one entry — no volume banding).","items":{"type":"object","properties":{"tier":{"type":"integer"},"volumeUsd":{"type":"string"},"sharePct":{"type":"string"},"points":{"type":"string"}}}},"rewardUsd":{"type":"string","example":"0.0125","description":"points × POINT_VALUE_USD"},"kashEarned":{"type":"string","example":"12.5"},"kashPriceUsd":{"type":"string","example":"0.001"},"balance":{"type":"string"},"lifetimeEarned":{"type":"string"},"vesting":{"type":"array","description":"30-day weekly tranches created by this accrual.","items":{"type":"object","properties":{"amount":{"type":"string"},"vestsAt":{"type":"string","format":"date-time"},"released":{"type":"boolean"}}}},"mintTxHash":{"type":"string"}}},"kash_AccrualResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/kash_Accrual"}}},"kash_Account":{"type":"object","properties":{"wallet":{"type":"string"},"balance":{"type":"string","example":"10012.5"},"balanceUsd":{"type":"string","example":"10.0125"},"lifetimeEarned":{"type":"string","example":"12.5"},"purchased":{"type":"string","example":"10000"},"vesting":{"type":"string","example":"12.5","description":"Earned KSH still locked."},"convertible":{"type":"string","example":"10000","description":"KSH redeemable at the desk right now (balance − vesting)."},"gate":{"type":"object","description":"The single holding gate: hold minHoldingKash to earn.","properties":{"minHoldingKash":{"type":"string","example":"10000"},"met":{"type":"boolean"},"shortfall":{"type":"string","example":"0"},"vestingPaused":{"type":"boolean","description":"True while below the gate — tranche maturation is suspended."}}},"vestingSchedule":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"string"},"vestsAt":{"type":"string","format":"date-time"},"released":{"type":"boolean"}}}},"kashPriceUsd":{"type":"string","example":"0.001"}}},"kash_AccountResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/kash_Account"}}},"kash_SubscribeRequest":{"type":"object","required":["wallet","tier"],"properties":{"wallet":{"type":"string"},"tier":{"type":"integer","minimum":2,"example":3},"paymentTxHash":{"type":"string","description":"On-chain USDC payment (required in real-USDC mode)."}}},"kash_StatusResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"price":{"type":"object"},"treasury":{"type":"object"},"supply":{"type":"object"},"rewards":{"type":"object"},"points":{"type":"object","description":"Marginal slice bounds + rates + point value."},"gate":{"type":"object"},"vesting":{"type":"object"},"desk":{"type":"object"},"epoch":{"type":"object"},"coverage":{"type":"object","description":"Circuit-breaker state and floors."},"chainMode":{"type":"string","enum":["mock","ethers","off"]}}}}},"kash_SettlementResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"weekKey":{"type":"string","example":"2026-08-01T00:00:00.000Z"},"windowStart":{"type":"string","format":"date-time"},"windowEnd":{"type":"string","format":"date-time"},"settlesAt":{"type":"string","format":"date-time"},"settled":{"type":"boolean"},"wallets":{"type":"integer"},"points":{"type":"string","description":"Decimal string, never a float"},"kash":{"type":"string"},"priceUsd":{"type":"string","nullable":true}}}}},"kash_ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"code":{"type":"string","description":"VALIDATION_ERROR | CONFLICT | NOT_FOUND | SERVICE_UNAVAILABLE"},"message":{"type":"string"},"details":{}}}}},"market-square_ErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"code":{"type":"string","description":"VALIDATION_ERROR | UNAUTHORIZED | FORBIDDEN | NOT_FOUND | CONFLICT | PAYMENT_FAILED | PROVIDER_ERROR | TOO_MANY_REQUESTS | INTERNAL_ERROR"},"message":{"type":"string"},"details":{}}}}},"market-square_HealthStatus":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"]},"service":{"type":"string"},"uptimeSeconds":{"type":"integer"}}},"market-square_DeepLink":{"type":"object","required":["kind","ref"],"properties":{"kind":{"type":"string","enum":["stream","store_item","listing","market","game","trade","prediction","activity","external"],"description":"What the link RESOLVES TO — an entity this service (or a sibling) can route to. Deliberately not the same list as Activity.type, which describes what is happening rather than what is linked: an `event` activity links to its `stream`, its `game`, or an `external` page. There is no `event` kind because there is no event entity to open."},"ref":{"type":"string"}}},"market-square_PostPreview":{"type":"object","required":["title","subtitle","imageUrl"],"description":"The card shown for a post's deepLink, written by whoever shared the activity. This service cannot describe a trade, a position or a game result — they live in other services it must not read — so the sharer supplies the words. They are therefore the author's CLAIM, not attested fact: render them as the author's, never with platform authority or money styling, and rely on the deep link to make the claim checkable in one tap. Only sent with a deepLink; a preview without one is rejected at creation.","properties":{"title":{"type":"string"},"subtitle":{"type":"string","nullable":true},"imageUrl":{"type":"string","nullable":true}}},"market-square_PublicProfile":{"type":"object","properties":{"id":{"type":"string","description":"Privy DID"},"username":{"type":"string","nullable":true},"displayName":{"type":"string","nullable":true},"bio":{"type":"string","nullable":true},"avatarUrl":{"type":"string","nullable":true},"coverUrl":{"type":"string","nullable":true,"description":"The photograph across the top of the profile. NULL is the ordinary state — most people never set one, and a header falling back to its generated artwork is a finished rendering rather than a placeholder. Nothing seeds a stock image here."},"website":{"type":"string","nullable":true,"description":"A link the person published on their own profile. NULL means they have not given one — a real answer, so render nothing rather than an empty row. Restricted to http(s) on WRITE, because this becomes an anchor href on a PUBLIC page and `z.string().url()` alone accepts `javascript:`, which would be stored XSS wearing the profile owner’s name. On PATCH /me: send null to clear it, omit it to leave it alone."},"city":{"type":"string","nullable":true,"description":"The self-declared place, as published. NULL means they have not said, and it stays null — never defaulted to a string, because a client deciding whether to draw the location pill at all cannot tell \"hasn’t said\" from \"\" once it has been."},"region":{"type":"string","nullable":true,"description":"See city."},"country":{"type":"string","nullable":true,"description":"ISO 3166-1 alpha-2 code (e.g. NG), self-declared from a list. Render the name on the client (e.g. Intl.DisplayNames)."},"continent":{"type":"string","enum":["AF","AN","AS","EU","NA","OC","SA"],"nullable":true,"description":"Derived from country: Africa, Antarctica, Asia, Europe, North America, Oceania, South America. LOCATION PRECISION: other people see city+region+country (city_region_country, the default), region+country, country, or only continent; fields beyond the owner’s precision are null. The owner always sees their own place in full."},"gender":{"type":"string","enum":["male","female"],"nullable":true,"description":"Self-declared: `male` or `female`, always lowercase. NULL means they have not said — render nothing. See city."},"role":{"type":"string","enum":["citizen","creator","ambassador","worldstreet"]},"verification":{"type":"string","enum":["none","pending","verified","lapsed"],"description":"Public signal only. The check renders ONLY on `verified`; `lapsed` means the subscription expired (history retained, renewing restores it). Billing dates are never exposed here — see GET /me/verification."},"orgBadge":{"type":"string","enum":["market","ark"],"nullable":true,"description":"Org affiliation chip shown beside the author name. Operator-assigned only — never derived from role, never self-assignable."},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"isFollowing":{"type":"boolean"},"mutualFollowers":{"type":"object","description":"People the VIEWER follows who also follow this profile — the \"Motara and 2 others follow them\" line. OPT-IN: absent unless the request asked for it with `withMutualFollowers=true`, because resolving it costs two extra queries per page, one of them proportional to how many people the caller follows — a surface that does not draw the line must not pay for it. ABSENT for anonymous readers and on the viewer’s own row, exactly like `isFollowing`: it is a statement about a relationship that does not exist without a viewer, and a zero would read as \"nobody you know follows them\" when nothing was checked. A genuine zero IS returned when a signed-in reader really shares nobody.","properties":{"count":{"type":"integer","description":"CAPPED AT 50. Read together with `countCapped`: when that is true this is a floor, not a total."},"countCapped":{"type":"boolean","description":"True when there are MORE than 50. It exists so a client can tell exactly 50 from at least 50 — without it a genuine 50 would have to render as \"50+\", and a cap indistinguishable from a real value is a quiet lie rather than a bound. The count is capped because the line answers \"do people I trust already follow this person\", and \"3 friends and 47 others\" and \"3 friends and 312 others\" are the same answer to that question."},"sample":{"type":"array","maxItems":3,"items":{"$ref":"#/components/schemas/market-square_ProfileSummary"},"description":"At most three, capped SERVER-side rather than by the client slicing a longer array. May be shorter than `count` suggests, and may drop a sampled profile that has since been deleted — the count still describes the edges."}}},"winkedByMe":{"type":"boolean","description":"Does the CALLER have an ACTIVE wink at this person — one still inside the cooldown window? OMITTED for an anonymous reader exactly as `isFollowing` is: a wink is a thing one person did to another, and with no viewer there is nobody to have done it. Same window the cooldown uses, so this and a refused wink can never disagree. A `wink` notification whose actor has this true is a MUTUAL wink — which is what tells \"they winked at you\" apart from \"you two winked at each other\"."},"winkedMe":{"type":"boolean","description":"Does this person have an active wink at the CALLER? Same omission rule, same window."}}},"market-square_Profile":{"description":"The caller’s OWN profile, returned by GET /me. It EXTENDS PublicProfile via allOf, so every field on PublicProfile — including city, region and gender — is part of this response even though they do not appear under `Profile.properties`. Read both halves of the allOf, or resolve the $ref, before concluding a field is missing: the second half adds only what is private to the caller (walletAddress, hasOnboarded, isAdmin, the verification dates, spotlightScore, timestamps).","allOf":[{"$ref":"#/components/schemas/market-square_PublicProfile"},{"type":"object","properties":{"walletAddress":{"type":"string","nullable":true},"hasOnboarded":{"type":"boolean","description":"Has this person completed onboarding, on the ACCOUNT rather than a device. Private to the viewer: it is here on GET /me and deliberately absent from PublicProfile, because whether somebody finished a product tour is nobody else’s business. Do NOT use it to skip the permission step — a microphone or notification grant belongs to one browser on one machine, so a person who allowed it on their phone genuinely has not on their laptop, and that step must stay per-device or you hide a prompt the browser is still going to raise. What it covers is the splash and the people step. Backfilled true for accounts that already claimed a username, which preserves the behaviour the username check gave before it existed."},"isAdmin":{"type":"boolean","description":"Operator flag. Present on GET /me so the console can show or hide itself; grants access to every /admin route with an ordinary Privy token."},"verifiedSince":{"type":"string","nullable":true},"paidThrough":{"type":"string","nullable":true},"lastPaidAt":{"type":"string","nullable":true},"spotlightScore":{"type":"string"},"privateBrowsing":{"type":"boolean","description":"Browse profiles without being listed as a viewer. Off by default; set with PATCH /me. Reciprocal: while on, GET /me/profile-views is refused and profileViewCount is null. Never on PublicProfile."},"profileViewCount":{"type":"integer","nullable":true,"description":"People who viewed this profile in the last 90 days — the same number as `total` on GET /me/profile-views. NULL while privateBrowsing is on."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}]},"market-square_ProfileSettings":{"type":"object","required":["notifications","chat","privacy"],"properties":{"notifications":{"type":"object","required":["friendsRooms","direct"],"properties":{"friendsRooms":{"type":"boolean","description":"\"Friends Room\": a person you follow starts a gist room."},"direct":{"type":"boolean","description":"\"Direct Notifications\": a direct message, a chat request, being added to a group."}}},"privacy":{"type":"object","required":["locationPrecision","showListening","personalizeByPlace"],"properties":{"locationPrecision":{"type":"string","enum":["city_region_country","region_country","country","continent"],"description":"How precisely OTHER people see your place: \"city, region and country\" (default), \"region and country\", \"country\" or \"continent\". Applies to the public profile and the People directory filters."},"showListening":{"type":"boolean","description":"\"Visibility on Space\" (default true): the people you follow can see which gist rooms you are listening in (GET /me/following/rooms), and your face can appear in a room’s `participants`. Off hides you from both. A room’s host is always shown in it."},"personalizeByPlace":{"type":"boolean","description":"\"Personalize based on places\" (default true): your for-you lane lifts posts by people whose DECLARED place matches yours (same city, region or country, as they choose to show it). Only the place on your profile is used; nothing records where you have been."}}},"chat":{"type":"object","required":["messagesFrom","allowHouseMembers","allowPastAudience"],"properties":{"messagesFrom":{"type":"string","enum":["no_one","everyone","verified"]},"allowHouseMembers":{"type":"boolean","description":"Let people you share a group with through. Default true."},"allowPastAudience":{"type":"boolean","description":"Let people who watched your gist rooms through. Default false."}}}}},"market-square_ProfilePhoto":{"type":"object","required":["id","url","thumbnailUrl","position","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","description":"The photo at a size fit to open full screen (up to 1280px wide)."},"thumbnailUrl":{"type":"string","description":"A 320x320 square crop for the 160px gallery tile. On storage without delivery transforms (local) it equals `url`."},"position":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"}}},"market-square_ProfilePhotoList":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ProfilePhoto"}}}},"market-square_ProfileViewEntry":{"type":"object","required":["viewer","viewedAt"],"properties":{"viewer":{"$ref":"#/components/schemas/market-square_ProfileSummary"},"viewedAt":{"type":"string","format":"date-time","description":"Their most recent view. Moves at most once per UTC day."}}},"market-square_ProfileViewPage":{"type":"object","required":["items","nextCursor","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ProfileViewEntry"}},"nextCursor":{"type":"string","nullable":true},"total":{"type":"integer","description":"People in the 90-day window, by the same rules as the rows. On every page."}}},"market-square_ProfileSummary":{"type":"object","description":"Hydrated author/actor summary — used for feed authors, comments, chat, spotlight, followers and conversation peers. Carries `isFollowing` for AUTHENTICATED callers wherever a Follow button could render; the field is OMITTED for anonymous callers and for the viewer own summary (you cannot follow yourself).","properties":{"id":{"type":"string"},"username":{"type":"string","nullable":true},"displayName":{"type":"string","nullable":true},"avatarUrl":{"type":"string","nullable":true},"role":{"type":"string"},"verification":{"type":"string"},"orgBadge":{"type":"string","enum":["market","ark"],"nullable":true,"description":"Org affiliation chip shown beside the author name. Operator-assigned only — never derived from role, never self-assignable."},"isFollowing":{"type":"boolean","description":"Viewer state: does the authenticated caller follow this profile? Omitted for anonymous callers and for the viewer own summary."},"winkedByMe":{"type":"boolean","description":"Does the CALLER have an ACTIVE wink at this person — one still inside the cooldown window? Omitted for anonymous callers and for the viewer’s own summary, exactly as isFollowing is. Resolved on notification actors, so a `wink` notification whose actor has this TRUE is a MUTUAL wink — which is what tells \"they winked at you\" apart from \"you two winked at each other\", two different sentences with two different buttons."},"winkedMe":{"type":"boolean","description":"Does this person have an active wink at the CALLER? Same omission rule and the same window."},"lastSeenAt":{"type":"string","nullable":true,"description":"Coarse presence, for a chat header’s \"Active 20m ago\". Written at most once per minute per profile, so treat it as a rounded time and never as a live signal. NULL means this profile has never been observed — render NOTHING, not \"a long time ago\": that would assert an observation this service never made."}}},"market-square_UpdateMeRequest":{"type":"object","description":"Every field is optional and at least one is required. On the NULLABLE fields (city, region, gender) an ABSENT key leaves the field alone while an explicit null CLEARS it — the same distinction PATCH /conversations/{id} documents for description and imageUrl. A profile form sends only what changed, so treating absent as a clear would wipe somebody’s city every time they edited their bio. A blank or whitespace-only string is treated as a clear rather than stored, so \"\" and null cannot mean two different things.","properties":{"username":{"type":"string","pattern":"^[a-z0-9_]{3,20}$"},"displayName":{"type":"string","maxLength":80},"bio":{"type":"string","maxLength":500},"avatarUrl":{"type":"string","format":"uri"},"coverUrl":{"type":"string","format":"uri","nullable":true,"description":"The profile cover. Null CLEARS it. A non-null value must be a URL this service produced for one of the CALLER’s own uploads — it is checked byte-for-byte, so an arbitrary address on the internet or another user’s upload is refused with 403 FORBIDDEN (the URL is well formed, it simply is not yours). Same rule a group picture and a message attachment already follow. Upload it through the ordinary presign path first and send back the URL you were given. NOTE the asymmetry: `avatarUrl` above is NOT checked this way, because it predates the rule and identity providers supply avatars from their own CDNs — tightening it would break every profile whose picture came from a social login, which is a decision to take on its own rather than a side effect of adding a cover."},"city":{"type":"string","maxLength":80,"nullable":true,"description":"Self-declared, free text. Not validated against a gazetteer: matching a places table is a promise to maintain one, and what matters is that two people who both say \"Lagos\" are findable together, which case-folded comparison gives. There is NO latitude, longitude or distance anywhere in this API, deliberately — a continuous position needs its own decisions about precision, retention, visibility and how somebody turns it off, and none of them are answered by a column. There is no street address either: a city is something people publish about themselves; a door number on a surface for meeting strangers needs a visibility rule before it needs storage."},"region":{"type":"string","maxLength":80,"nullable":true,"description":"Self-declared, free text. See city."},"country":{"type":"string","nullable":true,"description":"Two-letter ISO 3166-1 alpha-2 code from the list, any case (stored uppercase). Null or a blank clears it; a code not in the list is a 400. How precisely others see the place is `privacy.locationPrecision` on PATCH /me/settings."},"gender":{"type":"string","enum":["male","female"],"nullable":true,"description":"A choice of `male` or `female`. Accepted in any case and trimmed (`\" Female \"` is stored as `female`); null or a blank string CLEARS it; omit it to leave it alone. Any other value is a 400 and nothing is saved."},"privateBrowsing":{"type":"boolean","description":"Turn private browsing on or off. While on, profiles you view do not list you, and you cannot see your own viewers. A real boolean in both directions; anything else is a 400."},"hasOnboarded":{"type":"boolean","enum":[true],"description":"Mark onboarding complete. TRUE is the only accepted value and false is a 400, deliberately: completing onboarding cannot become less true, and a client sending false — a stale cache, a form serialising its whole state — would re-onboard an established person on every device they own. Refusing it at the boundary makes that unrepresentable rather than merely discouraged. It does not cover the permission step; see the field on Profile."}}},"market-square_FollowResult":{"type":"object","properties":{"following":{"type":"boolean"},"followerCount":{"type":"integer"}}},"market-square_BlockResult":{"type":"object","properties":{"blocked":{"type":"boolean"}}},"market-square_WinkResult":{"type":"object","description":"Identical for a delivered wink and one suppressed by a block — see the route.","properties":{"winked":{"type":"boolean"},"createdAt":{"type":"string"}}},"market-square_RepostResult":{"type":"object","properties":{"reposted":{"type":"boolean"},"repostCount":{"type":"integer"}}},"market-square_SearchItem":{"type":"object","description":"One result. `kind` selects which payload is present — profile | post | stream | product.","properties":{"kind":{"type":"string","enum":["profile","post","stream","product"]},"id":{"type":"string"},"profile":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"description":"kind=profile. Includes followerCount, and isFollowing when authed."},"post":{"allOf":[{"$ref":"#/components/schemas/market-square_Post"}],"description":"kind=post. Hydrated author + viewer state."},"stream":{"$ref":"#/components/schemas/market-square_Stream"},"product":{"$ref":"#/components/schemas/market-square_StoreItem"}}},"market-square_CategoryCount":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"count":{"type":"integer","nullable":true,"description":"null = owned by another service; never render as 0."}}},"market-square_GroupNotificationSettings":{"type":"object","required":["messages","rooms"],"properties":{"messages":{"type":"string","enum":["all","leaders_and_friends","none"]},"rooms":{"type":"string","enum":["all","leaders_and_friends","directed","none"]}}},"market-square_ConversationInvite":{"type":"object","required":["token","conversationId","createdBy","createdAt","expiresAt","maxUses","useCount"],"properties":{"token":{"type":"string","description":"22 URL-safe characters. Put it in your share URL."},"conversationId":{"type":"string","format":"uuid"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"maxUses":{"type":"integer","nullable":true,"description":"Null means uncapped."},"useCount":{"type":"integer"}}},"market-square_InvitePreview":{"type":"object","required":["id","title","description","imageUrl","memberCount","visibility","viewerIsMember","canJoin","valid","reason","expiresAt"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"imageUrl":{"type":"string","nullable":true},"memberCount":{"type":"integer"},"visibility":{"type":"string","enum":["public","private"]},"viewerIsMember":{"type":"boolean"},"canJoin":{"type":"boolean","description":"Whether POST /invites/{token}/accept would let THIS viewer in."},"valid":{"type":"boolean","description":"False when the link has expired or is used up."},"reason":{"type":"string","enum":["expired","used_up"],"nullable":true},"expiresAt":{"type":"string","format":"date-time"}}},"market-square_Conversation":{"type":"object","description":"A direct (1:1) or group conversation. Membership is NOT on this object — read it from GET /conversations/{id}/members, or from the members/memberCount on an inbox row.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["direct","group"],"description":"What the chat inbox tabs partition on: Gists = direct, Houses = group."},"title":{"type":"string","nullable":true,"description":"Groups only. A direct conversation is named by its peer."},"description":{"type":"string","nullable":true,"description":"Groups only: what the room is for. Null on a direct conversation, which the database enforces."},"imageUrl":{"type":"string","nullable":true,"description":"Groups only: the room’s picture, and always a URL this service issued. There is deliberately NO visibility field — there is no group directory and no join route, so every group is private in the only sense that can be observed, and a stored flag saying otherwise would be a claim nothing enforces."},"createdBy":{"type":"string","nullable":true,"description":"Groups only."},"visibility":{"type":"string","enum":["public","private"],"default":"private","description":"Whether somebody holding the group's link may JOIN it themselves via POST /conversations/{id}/join. It deliberately does NOT mean 'listed in a directory' — there is no group directory. A direct conversation is always private."},"requestState":{"type":"string","enum":["pending","accepted"],"description":"A conversation opened by somebody the recipient does not follow starts pending: it appears only under Gist Requests and contributes nothing to the unread badge until accepted."},"requestedBy":{"type":"string","nullable":true,"description":"Who asked, while requestState is pending. Cleared on accept."},"directKey":{"type":"string","nullable":true,"description":"Direct only: the two participant ids in canonical order. A uniqueness key, never a membership record — do not read it as one."},"lastMessageAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}}},"market-square_ConversationMember":{"type":"object","properties":{"profile":{"$ref":"#/components/schemas/market-square_ProfileSummary"},"role":{"type":"string","enum":["owner","member"],"description":"owner is the group’s creator — the only member who may rename it or remove somebody. A direct conversation has no owner."},"joinedAt":{"type":"string"}}},"market-square_MessageMedia":{"type":"object","description":"An attachment on a message. `url` is always one this service issued from its OWN upload path (POST /uploads or the presign pair) — a URL from anywhere else is refused, so this is never an arbitrary remote asset. `kind` is derived from the stored object rather than declared by the sender, so it cannot disagree with the bytes.","required":["url","kind"],"properties":{"url":{"type":"string"},"kind":{"type":"string","enum":["image","video","audio"]},"width":{"type":"integer","nullable":true,"description":"The sender’s own measurement, so the bubble can be laid out before the file loads. NULL means not measured — never zero."},"height":{"type":"integer","nullable":true},"durationSeconds":{"type":"integer","nullable":true,"description":"Audio and video only — the voice note’s length under its waveform. Sending it with an image is a 400 rather than a silently dropped field."}}},"market-square_ConversationMessage":{"type":"object","description":"A message carries text, media, or both — never neither, which the database states as a CHECK.","properties":{"id":{"type":"string"},"conversationId":{"type":"string"},"senderId":{"type":"string"},"text":{"type":"string","maxLength":2000,"nullable":true,"description":"NULL on a media-only message: a photo with no caption has no text. Not an empty string."},"media":{"allOf":[{"$ref":"#/components/schemas/market-square_MessageMedia"}],"nullable":true},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true,"description":"Something the message points at — today, the gist room its sender just opened. Opening a room from a house group posts one of these INTO that group, which is what lets the members find and join it; a private room is reachable only by them, so without the announcement it would be a door nobody knows about. A message may carry ONLY a deep link: the link is the message, and a caption would be words nobody wrote. Clients should render it as a join card using the same deep-link vocabulary posts and activities use. It is never settable by a client — POST /conversations/{id}/messages takes text and media only."},"status":{"type":"string","enum":["active","removed"]},"createdAt":{"type":"string"}}},"market-square_ConversationMessageView":{"allOf":[{"$ref":"#/components/schemas/market-square_ConversationMessage"},{"type":"object","description":"A message with its READ RECEIPT, as GET /conversations/{id}/messages returns it. Two states only: sent (the message exists — one check) and read (two checks, when readByAll). There is deliberately NO “delivered”: that needs a per-recipient acknowledgement no client sends, so a tick claiming it would assert something never observed. Both values are DERIVED from each member’s read watermark, so they are facts about the message and identical for every reader of the page.","properties":{"readBy":{"type":"integer","description":"How many members OTHER than the sender have read this message. The sender is never counted."},"readByAll":{"type":"boolean","description":"Every other member has read it — draw the second check. False in a conversation with nobody else in it."}}}]},"market-square_ConversationSummary":{"type":"object","description":"A conversation as an inbox row draws it. A direct row names itself with peer; a group row with title and members — exactly one is populated, so a client never has to guess which.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["direct","group"]},"title":{"type":"string","nullable":true,"description":"Groups only."},"description":{"type":"string","nullable":true,"description":"A group's own blurb. Groups only, and carried on the ROW so a list of houses does not need one full read per card — for a public group the reader is not in, those reads are membership gated anyway."},"imageUrl":{"type":"string","nullable":true,"description":"A group's picture. Groups only."},"visibility":{"type":"string","enum":["public","private"],"description":"Whether somebody holding the link may join it themselves. Was on the full conversation only, so a client could not tell a joinable house from a closed one without opening it. A direct conversation is always private."},"createdBy":{"type":"string","nullable":true,"description":"Who made the group. Null on a direct conversation and on groups predating the column."},"peer":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Direct only. Null on a group, which has no single peer."},"members":{"type":"array","items":{"$ref":"#/components/schemas/market-square_ProfileSummary"},"description":"Groups only, CAPPED at 4 and excluding the viewer — enough for a stack of avatars. memberCount is the true total; GET /conversations/{id}/members is the roster."},"memberCount":{"type":"integer"},"viewerIsMember":{"type":"boolean","description":"Does the CALLER belong to this house? Drives Join House versus View House. Present only where a house is listed for somebody ELSE (a profile’s House rail) and OMITTED entirely for an anonymous reader, who belongs to nothing — a `false` there would read as a checked answer rather than an unasked question. Resolved server-side because the client cannot work it out: the only list of its own houses is its inbox, and intersecting that per profile is a request storm for a button label."},"lastActiveAt":{"type":"string","nullable":true,"description":"Newest lastSeenAt across the OTHER members — the group header’s \"75 members · Active 3d ago\". The viewer is excluded, because their own presence is always now and would make every row read as active. NULL when nobody else has ever been observed: render nothing."},"lastMessage":{"allOf":[{"$ref":"#/components/schemas/market-square_ConversationMessage"}],"nullable":true},"lastSender":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Groups only: who sent lastMessage, for the preview’s sender prefix. Null on a direct conversation, where the sender is either the viewer or the peer the row already names."},"lastMessageAt":{"type":"string","nullable":true},"unreadCount":{"type":"integer"},"viewerRole":{"type":"string","enum":["owner","admin","member"],"description":"Groups only, on the caller's own inbox: their role in the group."},"notificationSettings":{"allOf":[{"$ref":"#/components/schemas/market-square_GroupNotificationSettings"}],"description":"Groups only, on the caller's own inbox: their notification settings for this group, so the settings screen needs no call per group."},"requestState":{"type":"string","enum":["pending","accepted"]},"requestedBy":{"type":"string","nullable":true}}},"market-square_Notification":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["follow","like","comment","comment_reply","comment_like","mention","repost","bookmark","ticket_purchased","stream_live","verification_resolved","role_resolved","message","speaker_request","tip_received","wink","chat_request","group_added","house_room"]},"actor":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"null for system notifications (verification/role decisions)."},"postId":{"type":"string","nullable":true},"streamId":{"type":"string","nullable":true},"commentId":{"type":"string","nullable":true,"description":"The comment this is about, on `comment`, `comment_reply` and `comment_like`. Without it the best a client can do is open the post, and a reply notification that lands somebody at the top of a post with ninety comments has not delivered them to the thing it is about. On `comment_reply` this is the REPLY’s id, which is not on the post’s top-level page — read GET /comments/{id} to learn its parentId and so which thread to expand."},"readAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"subject":{"type":"object","nullable":true,"description":"The thing the notification is about, NAMED, so a row can read \"commented on ‘Getting Started as a QA Engineer’\" rather than \"commented on your post\". NULL when the row is about a PERSON rather than a thing — a follow, a wink, a message — in which case render no subject line. Same shape and the same resolver as a tip’s `source`, so the two can never disagree about what a gist room is.","properties":{"kind":{"type":"string","enum":["post","stream","room"],"description":"`room` is a gist room — a stream with category `house` — reported separately so the client need not infer it."},"id":{"type":"string"},"title":{"type":"string","nullable":true,"description":"NULLABLE, and a real state rather than a gap: a post has no title field, so its title is its own opening text, and a picture-only post has none. Show the row without a subject line rather than inventing one. Truncated to 140 characters with an ellipsis."}}},"house":{"type":"object","nullable":true,"description":"On `house_room` only: the house the gist room was opened in, so the row can read \"{actor} opened a gist room in {title}\". `title` is the house’s CURRENT name. NULL on every other kind, and on a `house_room` row once the reader has left that house or it no longer exists — then use copy that names no house.","properties":{"conversationId":{"type":"string"},"title":{"type":"string","nullable":true}}},"group":{"type":"string","enum":["social","money","rooms","chat","account"],"description":"Which filter bucket this row falls in — the same vocabulary as the `group` query parameter. Carried on every row SO THE CLIENT NEVER RE-DERIVES IT: a client-side kind-to-group map silently drops every kind added after it ships, which is the failure that had `message` and `speaker_request` rendering as \"started following you\". Read this; do not rebuild it."}}},"market-square_TrendingDiscussion":{"type":"object","properties":{"tag":{"type":"string","description":"Lowercase, without the `#`."},"label":{"type":"string","description":"`#tag`, ready to render."},"postCount":{"type":"integer"},"participantCount":{"type":"integer","description":"Distinct authors. This is what the ranking uses — a discussion is people talking, not one person repeating a tag."},"viewCount":{"type":"integer","description":"Sum of the posts' own view tallies. Each post counts a person once however often they return, but someone reading three posts in a discussion counts three times — so this is REACH, and must not be presented as a number of people."}}},"market-square_TipCapability":{"type":"object","properties":{"enabled":{"type":"boolean"},"settlement":{"type":"string","enum":["rail","client-signed"],"description":"WHICH settlement the client must drive. `rail` means the server moves the money and the tip returns `confirmed`. `client-signed` means it cannot — no backend may move one person's tokens to another — so the response carries the recipient's wallet and the sender signs the transfer and reports it."},"minKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"maxKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"verifiedAuthorsOnly":{"type":"boolean"}}},"market-square_TipTransferRequest":{"type":"object","required":["txHash"],"properties":{"txHash":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$","description":"The transfer the sender signed. A CLAIM, not proof — settlement waits for the watcher to observe it on-chain with a matching amount and both wallets."}}},"market-square_SendTipRequest":{"type":"object","required":["amountKash"],"properties":{"amountKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"giftId":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,31}$","description":"Which gift the sender chose (`rose`, `lion`, `phoenix`), recorded so the recipient sees WHAT arrived and not only how much. A label, never a price: the amount above is the only authoritative figure, and this is deliberately not validated against a catalogue (the tray belongs to the client and grows without a deploy here)."}}},"market-square_TipWithContext":{"description":"A tip as the EARNINGS panel reads it — the sender and the thing already resolved. Both are hydrated server-side in batched reads because the client cannot do it: there is no profile-by-id GET to turn `fromUserId` into a person, and resolving a title per row would be one request per tip. Everything on Tip, plus:","allOf":[{"$ref":"#/components/schemas/market-square_Tip"},{"type":"object","properties":{"fromUser":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Who sent it. NULL when that profile is gone — a tip outlives the account that sent it, because the money moved, so the row keeps its amount and gift and simply names nobody. Treat the face as optional, not guaranteed."},"source":{"type":"object","nullable":true,"description":"What the tip was aimed at. NULL when it was aimed at a PERSON rather than a thing. Derived from the tip’s own postId/streamId rather than stored, so there is no second field to keep true.","properties":{"kind":{"type":"string","enum":["post","stream","room"],"description":"`room` is a gist room — a stream with category `house` — reported separately because \"gifted you during a gist room\" and \"gifted you on a broadcast\" are different sentences, and the client should not have to infer which."},"id":{"type":"string"},"title":{"type":"string","nullable":true,"description":"NULLABLE, and that is a real state rather than a gap. A post has no title field, so its title is its own opening text — a post that is only a picture has none, and a room with no topic set has none. Show the row without a source line rather than inventing one. Truncated to 140 characters with an ellipsis: a row shows one line, and thirty full post bodies is a payload nobody reads."}}}}}]},"market-square_Tip":{"type":"object","properties":{"id":{"type":"string"},"postId":{"type":"string"},"fromUserId":{"type":"string"},"toUserId":{"type":"string"},"amountKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"status":{"type":"string","enum":["pending","confirmed","failed"],"description":"`pending` means the rail has not answered — it is NOT \"sent\", and must never be presented to a user as though the money arrived."},"railRef":{"type":"string","nullable":true},"txHash":{"type":"string","nullable":true,"description":"The transfer the sender signed, on a client-settled tip. Null on a tip the rail moved, and null until the sender reports one."},"giftId":{"type":"string","nullable":true,"description":"The gift chosen, or null for a plain typed amount."},"createdAt":{"type":"string","format":"date-time"}}},"market-square_Pulse":{"type":"object","required":["bullish","neutral","bearish"],"properties":{"bullish":{"type":"integer"},"neutral":{"type":"integer"},"bearish":{"type":"integer"}}},"market-square_PulseResult":{"type":"object","required":["pulse","myChoice"],"properties":{"pulse":{"$ref":"#/components/schemas/market-square_Pulse"},"myChoice":{"type":"string","enum":["bullish","neutral","bearish"]}}},"market-square_MyPulse":{"type":"object","required":["myChoice"],"properties":{"myChoice":{"type":"string","enum":["bullish","neutral","bearish"],"nullable":true}}},"market-square_ViewResult":{"type":"object","required":["viewCount"],"properties":{"viewCount":{"type":"integer"}}},"market-square_BookmarkResult":{"type":"object","properties":{"bookmarked":{"type":"boolean"}}},"market-square_LikeResult":{"type":"object","properties":{"liked":{"type":"boolean"},"likeCount":{"type":"integer"}}},"market-square_PostMedia":{"type":"object","required":["url","kind","width","height","thumbnailUrl"],"properties":{"url":{"type":"string","description":"Delivered at a size for its kind, as mediaUrl is."},"kind":{"type":"string","enum":["image","video"],"description":"What the media service classified the upload as."},"width":{"type":"integer","nullable":true,"description":"The composer measurement, or null."},"height":{"type":"integer","nullable":true,"description":"See width."},"thumbnailUrl":{"type":"string","nullable":true,"description":"A video cover, or a derived poster frame on Cloudinary; null for a photo."}}},"market-square_CreatePostRequest":{"type":"object","required":["kind","text"],"properties":{"storyStyle":{"type":"object","required":["background","font"],"properties":{"background":{"type":"string","enum":["#7E3BEB","#5B05E6","#1D9BF0","#16A34A","#E84A4A","#F59E0B","#0F766E","#1F1F23"],"description":"Exact uppercase hex from the editor palette."},"font":{"type":"string","enum":["sans","serif","display","mono"],"description":"A token. Which typeface it means is the client decision."}},"description":"Optional, and ONLY with kind story: sending it with kind update is a 400, not ignored. Both fields required when the object is present."},"media":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"object","required":["url","kind"],"properties":{"url":{"type":"string","format":"uri"},"kind":{"type":"string","enum":["image","video"]},"width":{"type":"integer","minimum":1,"maximum":100000},"height":{"type":"integer","minimum":1,"maximum":100000},"thumbnailUrl":{"type":"string","format":"uri"}}},"description":"Several photos, or one photo or video, in order (up to 10). Send it INSTEAD of mediaUrl/mediaKind/thumbnailUrl/mediaWidth/mediaHeight; both together is a 400.\n\n**Ownership** — every `url` and `thumbnailUrl` must be byte-for-byte a URL this service issued for the AUTHOR’s own upload (POST /uploads/presign + /uploads/complete). An arbitrary address or someone else’s upload is 403 FORBIDDEN. The same rule now applies to `mediaUrl` and `thumbnailUrl`.\n\n**Rules (400)** — more than 10; a story with more than one; two or more items that are not all photos (a single item may be a video); an item whose declared `kind` is not what the upload is."},"mediaKind":{"type":"string","enum":["image","video"],"description":"Optional. The upload decides the kind; a value that disagrees with it is a 400. `mediaUrl` and `thumbnailUrl` must be the author’s own uploads (403 otherwise)."},"mediaWidth":{"type":"integer","minimum":1,"maximum":100000,"description":"The composer’s own measurement of the media, so a feed card can reserve the right box before the file lands — without it the card settles on first paint and everything below it jumps. Same shape and bounds as a message’s media: these size a layout, so an absurd value is a broken client rather than a tall photo. Send BOTH or neither; a width with no height reserves nothing, and the database enforces it."},"mediaHeight":{"type":"integer","minimum":1,"maximum":100000,"description":"See mediaWidth. Both together or neither."},"quotedPostId":{"type":"string","format":"uuid","description":"Quote another post. The original must exist and be visible (404 otherwise) and the quote counts toward its repostCount."},"mentions":{"type":"array","maxItems":25,"items":{"$ref":"#/components/schemas/market-square_Mention"}},"kind":{"type":"string","enum":["update","story"]},"text":{"type":"string","maxLength":2000},"mediaUrl":{"type":"string","nullable":true,"description":"DELIVERY url, not the stored original. Cloudinary-hosted assets come back with a transformation (`f_auto,q_auto` and a width cap for the surface), because a URL with nothing after `/upload/` delivers the full-resolution upload on every view — and on an autoplaying timeline that is what burns bandwidth. Assets on the service’s own storage are returned untouched. The stored object and its public id are unchanged, so this can be retuned without migrating anything; do NOT rewrite these paths client-side."},"thumbnailUrl":{"type":"string","format":"uri"},"deepLink":{"$ref":"#/components/schemas/market-square_DeepLink"},"preview":{"allOf":[{"$ref":"#/components/schemas/market-square_PostPreview"}],"description":"Card for the deepLink, supplied when an ARK activity is shared here. Requires deepLink: a preview without one is rejected, because a card that leads nowhere is the dead end it exists to remove. The service has stored this since the field shipped, but this spec did not describe it — so a client reading the spec alone concluded the platform could not carry a shared card."},"topics":{"type":"array","maxItems":20,"items":{"type":"string"},"description":"Shared-vocabulary topic keys; drives Explore filtering."}}},"market-square_Post":{"type":"object","properties":{"id":{"type":"string"},"authorId":{"type":"string"},"mediaWidth":{"type":"integer","nullable":true,"description":"The media's own size, measured by the COMPOSER and stored as sent — the service never sees the bytes on the presign path. Reserve the card's media box from these so it does not settle on first paint and shove everything below it; a timeline is where that shift is felt most, because it lands under a thumb already scrolling. NULL is a real answer (an older post, or a client that did not measure) and the card should fall back to its own aspect ratio — never invent a default, since a guessed 16:9 on a portrait photo is a worse shift than the one this removes. Both fields are set together or not at all, enforced by a CHECK."},"mediaHeight":{"type":"integer","nullable":true,"description":"See mediaWidth."},"storyStyle":{"type":"object","required":["background","font"],"properties":{"background":{"type":"string","enum":["#7E3BEB","#5B05E6","#1D9BF0","#16A34A","#E84A4A","#F59E0B","#0F766E","#1F1F23"],"description":"Exact uppercase hex from the editor palette."},"font":{"type":"string","enum":["sans","serif","display","mono"],"description":"A token. Which typeface it means is the client decision."}},"nullable":true,"description":"A TEXT story background and font, or null. Only a story carries one. Null means play on the default background, which is how every story posted before this existed plays."},"editedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the author last changed the text, or null if they never have. Draw the \"edited\" marker from this. Not `updatedAt`: that moves for counters and moderation, so it cannot answer \"did a person change these words\"."},"kind":{"type":"string","enum":["update","story"]},"text":{"type":"string"},"media":{"type":"array","items":{"$ref":"#/components/schemas/market-square_PostMedia"},"description":"Every photo or video on the post, in order: the rail. Always present; [] for a text post, and a one-item list for a post made with the single-media fields (including every post from before the list existed). `mediaUrl`, `mediaKind`, `thumbnailUrl`, `mediaWidth` and `mediaHeight` mirror the FIRST item, so read `media` and treat those as the legacy view of item one."},"mediaUrl":{"type":"string","nullable":true},"thumbnailUrl":{"type":"string","nullable":true,"description":"Creator-supplied cover image. OFTEN NULL — nothing generates or defaults one server-side, so a client leading with a large image must supply its own placeholder."},"topics":{"type":"array","items":{"type":"string"},"description":"Shared-vocabulary topic keys (GET /topics) — what the Explore chooser filters on."},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true},"storyExpiresAt":{"type":"string","nullable":true},"likeCount":{"type":"integer"},"commentCount":{"type":"integer","description":"Every comment on the post, REPLIES INCLUDED. The tally sits beside likes and reposts as \"how much conversation is here\", and a thread of forty replies under one comment reading 1 is the lie the number exists to avoid. It is decremented when a comment is deleted."},"likedByMe":{"type":"boolean","description":"Viewer state — whether the authenticated caller has liked this post. false for anonymous requests. Present on single-post reads and hydrated feed/story/profile items."},"mediaKind":{"type":"string","enum":["image","video"],"nullable":true,"description":"Drives the Reels lane; set from the upload kind."},"quotedPostId":{"type":"string","nullable":true},"preview":{"allOf":[{"$ref":"#/components/schemas/market-square_PostPreview"}],"nullable":true},"quotedPost":{"allOf":[{"$ref":"#/components/schemas/market-square_QuotedPost"}],"nullable":true},"mentions":{"type":"array","items":{"$ref":"#/components/schemas/market-square_Mention"}},"repostCount":{"type":"integer"},"bookmarkCount":{"type":"integer","description":"Denormalized bookmark total; also feeds the trending ranking."},"viewCount":{"type":"integer","description":"Distinct signed-in viewers. Never raised by a re-watch, and never by the author."},"tipCount":{"type":"integer","description":"Confirmed tips received on this post. Pending tips are not counted."},"tipTotalKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"Sum of CONFIRMED tips on this post, as a decimal string."},"repostedByMe":{"type":"boolean","description":"Viewer state — whether the caller has reposted. false when anonymous."},"bookmarkedByMe":{"type":"boolean","description":"Viewer state — whether the authenticated caller has bookmarked (\"Arkmarked\") this post. false for anonymous requests. Hydrated on the same surfaces as likedByMe."},"status":{"type":"string","enum":["active","removed"]},"createdAt":{"type":"string"}}},"market-square_Mention":{"type":"object","required":["type","id","label","handle"],"properties":{"type":{"type":"string","enum":["profile","group"]},"id":{"type":"string"},"label":{"type":"string"},"handle":{"type":"string"}}},"market-square_QuotedPost":{"type":"object","description":"The quoted original, hydrated ONE level deep only. A removed/expired original comes back with unavailable=true and empty fields rather than being dropped.","properties":{"id":{"type":"string"},"text":{"type":"string"},"mediaUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"unavailable":{"type":"boolean"},"author":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true}}},"market-square_Comment":{"type":"object","properties":{"id":{"type":"string"},"postId":{"type":"string"},"authorId":{"type":"string"},"author":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Hydrated author summary (list endpoints)."},"parentId":{"type":"string","nullable":true,"description":"The comment this replies to, or NULL for a top-level one. ONE LEVEL DEEP: a parent is always a top-level comment, never another reply. To reply to a reply, send the TOP-LEVEL id here and mention the person in the text. GET /posts/{id}/comments returns top-level comments ONLY, so replies never interleave with the thread — fetch them from GET /comments/{id}/replies."},"mentions":{"type":"array","maxItems":25,"items":{"$ref":"#/components/schemas/market-square_Mention"},"description":"People named in the comment. Send them STRUCTURED from a picker when you have one — that resolves an ambiguity the server can only guess at. Handles typed as plain text are ALSO resolved server-side and merged in, so \"@ada\" works from a box with no picker; yours win on conflict, and a handle resolving to nobody is dropped rather than kept as a mention linking nowhere."},"replyToCommentId":{"type":"string","nullable":true,"description":"Which comment this reply ANSWERED, when that is not the parent itself. Replying to a reply files the new comment under the SAME top-level parent — one visible level — and records the answered reply here. Null on a top-level comment and on a reply made directly to the parent."},"replyTo":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"The person `replyToCommentId` belongs to, resolved — render the \"@username\" prefix from THIS rather than by parsing the text. Null when the reply answered the parent directly, and null when that account is gone: render the reply with no prefix rather than a blank mention."},"replyCount":{"type":"integer","description":"Replies to THIS comment — what \"View N replies\" reads. Always 0 on a reply, since a reply cannot be a parent. Decremented when a reply is deleted, so the affordance never opens a thread shorter than it promised."},"likeCount":{"type":"integer"},"likedByMe":{"type":"boolean","description":"Has the CALLER liked this comment? OMITTED entirely for an anonymous reader rather than sent as false — the same rule as isFollowing. A false is a checked answer, and with no viewer nothing was checked."},"text":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"}}},"market-square_CreateReportRequest":{"type":"object","required":["targetType","targetId","reason"],"properties":{"targetType":{"type":"string","enum":["post","comment","profile","stream_message"]},"targetId":{"type":"string"},"reason":{"type":"string","enum":["spam","abuse","scam","other"]},"note":{"type":"string","maxLength":500}}},"market-square_Report":{"type":"object","properties":{"id":{"type":"string"},"reporterId":{"type":"string"},"targetType":{"type":"string"},"targetId":{"type":"string"},"reason":{"type":"string"},"note":{"type":"string","nullable":true},"status":{"type":"string","enum":["open","actioned","dismissed"]},"createdAt":{"type":"string"}}},"market-square_FeedItem":{"type":"object","properties":{"id":{"type":"string"},"repostedBy":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"description":"Present when the item appears because this profile reposted it."},"type":{"type":"string","enum":["post","stream","activity","platform_event"]},"occurredAt":{"type":"string"},"deepLink":{"$ref":"#/components/schemas/market-square_DeepLink"},"post":{"$ref":"#/components/schemas/market-square_Post"},"stream":{"$ref":"#/components/schemas/market-square_Stream"},"activity":{"$ref":"#/components/schemas/market-square_Activity"},"platformEvent":{"$ref":"#/components/schemas/market-square_FeedEvent"}}},"market-square_FeedEvent":{"type":"object","properties":{"id":{"type":"string"},"source":{"type":"string"},"eventKey":{"type":"string"},"title":{"type":"string"},"body":{"type":"string","nullable":true},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true},"occurredAt":{"type":"string"}}},"market-square_CreateStreamRequest":{"type":"object","required":["title","category","visibility"],"properties":{"chatAccess":{"type":"string","enum":["open","followers"],"default":"open","description":"Who may TYPE in the room's chat. `followers` admits the host, the host's followers, and anyone the host has approved as a speaker; everyone else gets 403 on send. Gates WRITING only — reading is never restricted by this. Omitting it keeps the historic behaviour."},"title":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"category":{"type":"string","enum":["worldstreet","music","podcast","gaming","other","house"]},"thumbnailUrl":{"type":"string","format":"uri"},"audience":{"type":"string","enum":["public","private"],"description":"WHO may find the room, as distinct from `visibility`, which is a door CHARGE. `public` (default) is listed everywhere a room can be listed — home, the street, search, the live lane. `private` is reachable ONLY by members of `houseConversationId` and appears in no listing for anybody else; it is filtered in the QUERY, not by the caller. A private room whose house group is later deleted becomes visible to NOBODY rather than silently public — the check fails closed."},"houseConversationId":{"type":"string","format":"uuid","description":"The group conversation a PRIVATE room belongs to. Required when `audience` is `private` (400 without it — a private room naming no group could never be entered), must be a group (404), and the caller must already be a member of it (403), so nobody can park a room inside somebody else’s house."},"topics":{"type":"array","items":{"type":"string"},"maxItems":20,"description":"Keys from the shared vocabulary served by GET /topics — the SAME keys that tag posts and express a reader’s interests, which is what makes a chosen topic filter anything. Validated against the topics table and REJECTED BY NAME if unknown, so never hard-code a list here: fetch /topics and offer what it returns. The gist-room composer sends up to five."},"scheduledAt":{"type":"string","format":"date-time","description":"Optional. Omitted means now — the result always carries one."},"visibility":{"type":"string","enum":["public","ticketed"]},"ticketPriceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"vipPriceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"description":"Where the broadcast points — e.g. { kind: \"game\", ref: \"<matchId>\" } for a chess match being streamed, so viewers can open the board."}}},"market-square_FollowingRoom":{"allOf":[{"$ref":"#/components/schemas/market-square_Stream"},{"type":"object","required":["friends","friendCount"],"properties":{"friends":{"type":"array","maxItems":5,"items":{"$ref":"#/components/schemas/market-square_ProfileSummary"},"description":"Followed people listening in the room, most recent first."},"friendCount":{"type":"integer","description":"How many followed people are listening; `friends` shows at most five of them."}}}]},"market-square_Stream":{"type":"object","properties":{"house":{"type":"object","nullable":true,"description":"The house this gist room was opened from. Present on GET /streams/{id} ONLY — the room header is its consumer, and hydrating it for every card on a discovery page would cost a query per row that no card draws. Null when the room belongs to no house, and null (rather than 404) when the house was deleted. Readable by a NON-member on purpose: the room previously carried only `houseConversationId`, so naming the house meant reading the conversation, which is membership gated — the header therefore worked only for people already inside, and Join House had nothing to name. It is a doorplate, not a way past the gate: no member list, no messages, no last activity. Use `viewerIsMember` to decide whether to draw Join House, and `visibility` to know whether joining is possible at all (only a `public` group can be joined from the room). `viewerIsMember` is false for a signed-out reader rather than unknown, so there is no third state to render.","properties":{"id":{"type":"string"},"title":{"type":"string","nullable":true},"imageUrl":{"type":"string","nullable":true},"memberCount":{"type":"integer"},"visibility":{"type":"string","enum":["public","private"]},"viewerIsMember":{"type":"boolean"}}},"chatAccess":{"type":"string","enum":["open","followers"],"description":"Who may TYPE in the room's chat. `followers` admits the host, the host's followers, and anyone the host approved as a speaker; everyone else gets 403 on send. Gates WRITING only — reading is never restricted by this."},"audience":{"type":"string","enum":["public","private"],"description":"Who may find this room. See CreateStreamRequest.audience. Not `visibility`, which is about paying to get in."},"houseConversationId":{"type":"string","nullable":true,"description":"The house group a PRIVATE room belongs to. Null on a public one."},"id":{"type":"string"},"ownerId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"type":"string"},"thumbnailUrl":{"type":"string","nullable":true},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true},"viewerCount":{"type":"integer","nullable":true,"description":"Viewers watching RIGHT NOW, present on list AND detail responses so a discovery grid never has to fall back to per-item detail calls. Null unless status is `live` — a non-live stream shows nothing rather than a stale or confidently-zero number. Distinct from `peakViewers`, which is a historical high-water mark and must not be rendered as a live figure. Derived from the view sessions that have sent a heartbeat within the last three heartbeat intervals, read in one batched lookup per page: it holds for as long as a viewer keeps beating and falls only once they stop."},"participants":{"type":"array","maxItems":3,"items":{"$ref":"#/components/schemas/market-square_ProfileSummary"},"description":"Up to three people currently in a GIST ROOM — host first, then the most recent joiners. Present on the SINGLE-STREAM read only, and only for a live room whose category is `house`. ABSENT on every other stream, which is a privacy decision rather than an optimisation: on a room, being seen in it is the point, while on a broadcast the identical field would publish who is WATCHING, by name and face, and watching is not joining. NOT THE SAME READING AS viewerCount: presence is keyed by view SESSION, and a signed-out viewer’s session has no person behind it, so this array is routinely SHORTER than viewerCount and can be empty while a room is busy. Treat the two as independent readings of one room — never derive a number of \"others\" from the difference. An EMPTY array means \"a room with nobody resolvable in it\"; ABSENT means \"not a room at all\"."},"topics":{"type":"array","items":{"type":"string"},"description":"Shared-vocabulary topic keys (GET /topics). This is the taxonomy discovery filters on; `category` is a legacy alias kept for compatibility and was mapped into these keys by migration 020."},"owner":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"The host, hydrated on EVERY stream surface (list, detail, deep-link lookup, create/patch/go-live responses, feed rail, search hits, /me/tickets embeds) so a card or a join button can say whose broadcast this is. Batch-loaded per page. Null only if the profile row vanished — the key itself is always present."},"status":{"type":"string","enum":["scheduled","live","ended","cancelled"]},"scheduledAt":{"type":"string","nullable":true,"description":"Never null while status is `scheduled` — enforced by a database CHECK. Null only on streams that have moved past scheduling without one (historic rows)."},"startedAt":{"type":"string","nullable":true},"endedAt":{"type":"string","nullable":true},"visibility":{"type":"string","enum":["public","ticketed"]},"ticketPriceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number","nullable":true},"vipPriceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number","nullable":true},"vipEarlyAccessMinutes":{"type":"integer","nullable":true},"replayUrl":{"type":"string","nullable":true},"peakViewers":{"type":"integer"},"likeCount":{"type":"integer","description":"Hearts sent during the broadcast. Repeatable per viewer — this is applause, not a per-person vote — and counted rather than stored one row per tap."},"totalViewSeconds":{"type":"integer"},"endedReason":{"type":"string","enum":["ended_by_host","host_disconnected"],"nullable":true,"description":"Why the stream ended: manual end vs. auto-end by the orphan reaper after the host-disconnect grace window."},"createdAt":{"type":"string"}}},"market-square_StreamDetail":{"allOf":[{"$ref":"#/components/schemas/market-square_Stream"},{"type":"object","properties":{"viewerCount":{"type":"integer"},"myTicket":{"$ref":"#/components/schemas/market-square_Ticket"}}}]},"market-square_SpeakerRequest":{"type":"object","description":"On GET /speaker-requests/me an APPROVED request also carries joinUrl/joinToken/expiresAt — the publisher credentials the guest needs to go live. They are absent in every other state.","properties":{"joinUrl":{"type":"string","description":"Approved only — LiveKit URL."},"joinToken":{"type":"string","description":"Approved only — canPublish token."},"expiresAt":{"type":"string","description":"Approved only — token expiry."},"id":{"type":"string"},"streamId":{"type":"string"},"userId":{"type":"string"},"status":{"type":"string","enum":["pending","approved","denied","withdrawn","removed"],"description":"`approved` is the state that carries publish rights. `removed` = host revoked a live speaker, `denied` = never granted, `withdrawn` = the speaker stepped down."},"createdAt":{"type":"string"},"resolvedAt":{"type":"string","nullable":true},"resolvedBy":{"type":"string","nullable":true}}},"market-square_StreamIngest":{"type":"object","description":"url + roomToken (publisher grant) are always present for browser WebRTC publishing; rtmpUrl/streamKey are null when RTMP ingress is unavailable (degraded go-live). IDENTITY: roomToken is minted with `<ownerId>#broadcaster` and the RTMP ingress participant joins as `<ownerId>#rtmp` — both carry the owner, and both are suffixed so a host holding several connections (publisher token, RTMP push, their own viewer tab) cannot evict themselves, since LiveKit treats identity as unique per room. Strip any `#...` suffix to get the user id. It was formerly the bare literal `broadcaster`, with no user id at all, which left clients unable to tell that the publisher and the host profile were one person. The token also carries the host name and the same participant metadata (username, avatarUrl, verification, orgBadge) every other token carries.","properties":{"url":{"type":"string","nullable":true,"description":"Client-reachable LiveKit URL."},"rtmpUrl":{"type":"string","nullable":true},"streamKey":{"type":"string","nullable":true},"roomToken":{"type":"string","nullable":true}}},"market-square_TicketTierRequest":{"type":"object","required":["tier"],"properties":{"tier":{"type":"string","enum":["standard","vip"]}}},"market-square_TicketQuote":{"type":"object","properties":{"streamId":{"type":"string"},"tier":{"type":"string"},"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"expiresAt":{"type":"string"}}},"market-square_Ticket":{"type":"object","properties":{"id":{"type":"string"},"streamId":{"type":"string"},"buyerId":{"type":"string"},"tier":{"type":"string","enum":["standard","vip"]},"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"currency":{"type":"string","enum":["KASH"]},"status":{"type":"string","enum":["pending","confirmed","failed","refunded"]},"railRef":{"type":"string","nullable":true},"createdAt":{"type":"string"},"confirmedAt":{"type":"string","nullable":true}}},"market-square_PlaybackGrant":{"type":"object","properties":{"url":{"type":"string"},"token":{"type":"string"},"expiresAt":{"type":"string"}}},"market-square_HeartbeatRequest":{"type":"object","required":["mode"],"properties":{"sessionId":{"type":"string","format":"uuid"},"mode":{"type":"string","enum":["live","replay"]}}},"market-square_StreamMessage":{"type":"object","properties":{"id":{"type":"string"},"streamId":{"type":"string"},"authorId":{"type":"string"},"author":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Hydrated author summary (chat listing)."},"text":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"}}},"market-square_StreamReactionResult":{"type":"object","properties":{"likeCount":{"type":"integer"}}},"market-square_StreamStats":{"type":"object","properties":{"peakViewers":{"type":"integer"},"uniqueViewers":{"type":"integer"},"totalViewSeconds":{"type":"integer"},"messages":{"type":"integer"},"ticketsSold":{"type":"integer"},"kashEarned":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"}}},"market-square_HostStreamEvent":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["ticket_purchased","follow"]},"occurredAt":{"type":"string"},"profile":{"allOf":[{"$ref":"#/components/schemas/market-square_ProfileSummary"}],"nullable":true,"description":"Ticket buyer or new follower."},"amountKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"ticket_purchased only."}}},"market-square_CreateActivityRequest":{"type":"object","required":["type","title","startsAt"],"properties":{"type":{"type":"string","enum":["game","stream","event"],"description":"What is happening. NOT the same vocabulary as deepLink.kind, which says what entity the link resolves to — an `event` activity linking to its broadcast carries kind `stream`, one with only a web page carries `external`."},"title":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"startsAt":{"type":"string","format":"date-time"},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true,"description":"OPTIONAL — an activity is an announcement, and the thing it points at often does not exist yet (\"Chess tournament, Saturday 8pm\"). Omit it and the activity renders with no CTA. A partial link (kind without ref, or the reverse) is rejected."}}},"market-square_Activity":{"type":"object","properties":{"id":{"type":"string"},"hostId":{"type":"string"},"type":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"startsAt":{"type":"string"},"deepLink":{"allOf":[{"$ref":"#/components/schemas/market-square_DeepLink"}],"nullable":true,"description":"Null when the activity has nothing to link to yet."},"status":{"type":"string","enum":["scheduled","live","completed","cancelled"]},"createdAt":{"type":"string"}}},"market-square_StoreItem":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"tagline":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"category":{"type":"string","enum":["app","product","service"]},"iconUrl":{"type":"string","nullable":true},"bannerUrl":{"type":"string","nullable":true},"pricing":{"type":"string","enum":["free","kash"]},"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number","nullable":true},"actionKind":{"type":"string","enum":["open","download","purchase"]},"actionUrl":{"type":"string"},"ownerTeam":{"type":"string"},"status":{"type":"string","enum":["draft","published","archived"]},"installCount":{"type":"integer"},"createdAt":{"type":"string"}}},"market-square_StoreOrder":{"type":"object","properties":{"id":{"type":"string"},"itemId":{"type":"string"},"buyerId":{"type":"string"},"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"status":{"type":"string","enum":["pending","confirmed","failed","refunded"]},"railRef":{"type":"string","nullable":true},"createdAt":{"type":"string"}}},"market-square_VerificationRule":{"type":"object","properties":{"eligibility":{"type":"object","properties":{"minFollowers":{"type":"integer"},"minParticipationScore":{"type":"number"}}},"paid":{"type":"object","properties":{"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"}}},"economics":{"type":"string","enum":["proposed"]}}},"market-square_MyVerification":{"type":"object","description":"The owner's view — the only place billing dates are exposed.","properties":{"status":{"type":"string","enum":["none","pending","verified","lapsed"]},"verifiedSince":{"type":"string","nullable":true},"paidThrough":{"type":"string","nullable":true},"daysRemaining":{"type":"integer"},"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"periodDays":{"type":"integer"},"trialDays":{"type":"integer"},"canRenew":{"type":"boolean"},"economics":{"type":"string","enum":["live","proposed"]},"latestRequest":{"allOf":[{"$ref":"#/components/schemas/market-square_VerificationRequest"}],"nullable":true}}},"market-square_VerificationRequest":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"type":{"type":"string","enum":["earned","paid"]},"status":{"type":"string","enum":["pending","approved","rejected"]},"note":{"type":"string","nullable":true},"createdAt":{"type":"string"},"resolvedAt":{"type":"string","nullable":true}}},"market-square_UploadLimits":{"type":"object","required":["maxImageBytes","maxVideoBytes","maxAudioBytes","imageContentTypes","videoContentTypes","audioContentTypes","maxVideoSeconds"],"properties":{"maxImageBytes":{"type":"integer","description":"MEDIA_MAX_IMAGE_MB in bytes. Default 26214400 (25 MB)."},"maxVideoBytes":{"type":"integer","description":"MEDIA_MAX_VIDEO_MB in bytes. Default 209715200 (200 MB). Deliberately below the 500 MB the service can accept: uploads are NOT transcoded and the feed autoplays clips, so the viewer downloads the original without opting in. Operators may raise it once that changes."},"maxAudioBytes":{"type":"integer","description":"MEDIA_MAX_AUDIO_MB in bytes. Default 10485760 (10 MB). A separate number from the video cap on purpose: a voice note is not a clip, and sharing the video cap would let one be a file nobody could listen to on mobile data."},"maxVideoSeconds":{"type":"integer","description":"ADVISORY clip-length guidance (MEDIA_MAX_VIDEO_SECONDS, default 90). NOT ENFORCED: reading a duration means demuxing the file, and on the presign path this service never sees the bytes, so a client can ignore this. Clients SHOULD read the duration locally and refuse an over-long clip before uploading, naming this limit and the clip's actual length. The enforced limit is maxVideoBytes."},"imageContentTypes":{"type":"array","items":{"type":"string"},"description":"Exact allowlist. Use it for the picker `accept` and for pre-validation."},"videoContentTypes":{"type":"array","items":{"type":"string"},"example":["video/mp4","video/webm","video/quicktime"],"description":"Includes `video/quicktime` (an iPhone .mov). Stored as uploaded, never transcoded by this service; the delivered URL carries a per-browser format transform, so a client should play the returned URL rather than assume the original container."},"audioContentTypes":{"type":"array","items":{"type":"string"},"description":"Voice notes. Same allowlist rules as the other two kinds."}}},"market-square_UploadResult":{"type":"object","properties":{"url":{"type":"string","description":"The public media URL. Its SHAPE depends on the configured store, so treat it as opaque: MEDIA_PUBLIC_BASE_URL + stored key on an S3-compatible target, or https://res.cloudinary.com/<cloud>/<image|video>/upload/<key> on Cloudinary."},"kind":{"type":"string","enum":["image","video","audio"]},"contentType":{"type":"string"},"bytes":{"type":"integer"}}},"market-square_PresignedUpload":{"type":"object","properties":{"uploadUrl":{"type":"string","description":"Send the bytes here — directly, not via your own backend. Treat the host as opaque: it is the configured media store, which can change without an API change."},"method":{"type":"string","enum":["POST","PUT"],"description":"POST = multipart form, `fields` first and the file LAST. PUT = the raw file as the body, sending `headers` as given. Branch on this rather than assuming: which one you get depends on the store this deployment is configured with."},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Form fields that MUST be submitted first, before the file part, exactly as given — they carry the signature and its conditions."},"key":{"type":"string","description":"Pass this to POST /uploads/complete once the upload finishes."},"publicUrl":{"type":"string","description":"What the URL will be once completed. Do not attach it before completing."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers to send with a PUT. Absent for a POST."},"expiresAt":{"type":"string"},"kind":{"type":"string","enum":["image","video","audio"]},"maxBytes":{"type":"integer","description":"The cap baked into the signature for this kind."}}},"market-square_Topic":{"type":"object","properties":{"key":{"type":"string","description":"Stable slug. The SAME key tags content and expresses an interest — that shared vocabulary is the whole design."},"label":{"type":"string","description":"Display string for the chip."},"sortOrder":{"type":"integer","description":"Ascending display order. With ?surface= it is the position on THAT surface, so the same topic can carry different values on different screens."}}},"market-square_RoleApplication":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"requestedRole":{"type":"string","enum":["creator"]},"note":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","approved","rejected"]},"createdAt":{"type":"string"},"resolvedAt":{"type":"string","nullable":true}}},"market-square_AdminCreateStoreItemRequest":{"type":"object","required":["slug","name","category","pricing","actionKind","actionUrl","ownerTeam"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]{2,60}$"},"name":{"type":"string"},"tagline":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["app","product","service"]},"iconUrl":{"type":"string","format":"uri"},"bannerUrl":{"type":"string","format":"uri"},"pricing":{"type":"string","enum":["free","kash"]},"priceKash":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"KASH amount as a decimal string — never a number"},"actionKind":{"type":"string","enum":["open","download","purchase"]},"actionUrl":{"type":"string"},"ownerTeam":{"type":"string"},"status":{"type":"string","enum":["draft","published","archived"]}}}},"parameters":{"rwa_AssetId":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Canonical id `{chain}:{address}`","example":"ethereum:0x96F6eF951840721AdBF46Ac996b59E0235CB985C"},"trade_Address":{"name":"address","in":"path","required":true,"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"}},"trade_SwapId":{"name":"swapId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"trade_IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":128}},"trade_SolanaSignature":{"name":"signature","in":"query","required":true,"schema":{"type":"string","description":"base58 signature","minLength":32,"maxLength":88}}},"responses":{"rwa_NotFound":{"description":"Unknown asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_ErrorResponse"}}}},"rwa_BadRequest":{"description":"Validation failed, unsupported chain, or permissioned asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/rwa_ErrorResponse"}}}},"trade_ValidationError":{"description":"Request validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_ErrorEnvelope"}}}},"trade_Unauthorized":{"description":"A valid bearer token is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_ErrorEnvelope"}}}},"trade_Forbidden":{"description":"The authenticated identity is not allowed to perform this operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_ErrorEnvelope"}}}},"trade_TokenNotFound":{"description":"The address is not a readable ERC-20 token contract on configured Base","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_ErrorEnvelope"}}}},"trade_SwapNotFound":{"description":"The swap does not exist or does not belong to the authenticated identity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_ErrorEnvelope"}}}},"trade_TradeRejected":{"description":"Risk, liquidity, route, balance, or trading policy rejected the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_ErrorEnvelope"}}}},"perp_NotFound":{"description":"Unknown market (PAIR_NOT_FOUND)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ErrorResponse"}}}},"perp_BadRequest":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/perp_ErrorResponse"}}}},"kash_BadRequest":{"description":"Validation failed (VALIDATION_ERROR)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ErrorResponse"}}}},"kash_Unauthorized":{"description":"Missing or invalid identity token (UNAUTHORIZED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ErrorResponse"}}}},"kash_Conflict":{"description":"The request contradicts existing state (CONFLICT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/kash_ErrorResponse"}}}}},"securitySchemes":{"trade_bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Privy access token","description":"Privy access token issued for the configured Privy App ID."},"trade_adminApiKey":{"type":"apiKey","in":"header","name":"x-admin-api-key","description":"Internal administrator API key."},"perp_waitlistAdminKey":{"type":"http","scheme":"bearer","description":"The service operator’s WAITLIST_ADMIN_KEY (admin listing only)."},"perp_perpsAdminKey":{"type":"http","scheme":"bearer","description":"The service operator’s PERPS_ADMIN_KEY (reward status + claim only)."},"earn_bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Privy access token"},"kash_adminKey":{"type":"http","scheme":"bearer","description":"KASH_TEST_ADMIN_KEY — test-only wallet reset routes."},"kash_railKey":{"type":"http","scheme":"bearer","description":"KASH_RAIL_API_KEY — the service rail. Proves the CALLER is a trusted service; it is not consent from the wallet holder, which travels separately as a permit on each debit."},"kash_privyIdentity":{"type":"apiKey","in":"header","name":"privy-id-token","description":"The session's Privy identity token, forwarded by the gateway. The service verifies it and reads the caller's embedded wallet from it."},"market-square_bearerAuth":{"type":"http","scheme":"bearer","description":"Privy access token"},"market-square_adminKey":{"type":"apiKey","in":"header","name":"x-internal-admin-key","description":"Shared secret for machine-to-machine callers and bootstrapping. Carries no identity, so actions it authorises are anonymous in the audit log — prefer an admin user token (bearerAuth from an is_admin profile), which names the operator."},"user-management_PrivyAccessToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"user-management_AdminApiKey":{"type":"apiKey","in":"header","name":"x-admin-api-key"},"user-management_basicAuth":{"type":"http","scheme":"basic"}},"requestBodies":{"trade_WalletChallenge":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletAddress"],"properties":{"walletAddress":{"type":"string"}}}}}},"trade_WalletVerification":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["challengeId","signature"],"properties":{"challengeId":{"type":"string","format":"uuid"},"signature":{"type":"string","pattern":"^0x[a-fA-F0-9]+$"}}}}}},"trade_Swap":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["side","tokenAddress","amount","walletAddress"],"properties":{"side":{"type":"string","enum":["BUY","SELL"]},"tokenAddress":{"type":"string"},"amount":{"type":"string"},"walletAddress":{"type":"string"},"slippageBps":{"type":"integer"}}}}}},"trade_Submission":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletAddress","callIndex"],"properties":{"walletAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"callIndex":{"type":"integer","minimum":0},"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$"},"userOperationHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$"}},"oneOf":[{"required":["transactionHash"],"not":{"required":["userOperationHash"]}},{"required":["userOperationHash"],"not":{"required":["transactionHash"]}}]}}}},"trade_SolanaWalletChallenge":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletAddress"],"properties":{"walletAddress":{"type":"string","description":"base58 Solana address","minLength":32,"maxLength":44}}}}}},"trade_SolanaWalletVerification":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["challengeId","signature"],"properties":{"challengeId":{"type":"string","format":"uuid"},"signature":{"type":"string","description":"base58 Ed25519 signature","minLength":80,"maxLength":90}}}}}},"trade_SolanaSwap":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["side","tokenAddress","amount","walletAddress"],"properties":{"side":{"type":"string","enum":["BUY","SELL"]},"tokenAddress":{"type":"string","description":"base58 SPL-token mint","minLength":32,"maxLength":44},"amount":{"type":"string"},"walletAddress":{"type":"string","description":"base58 Solana address","minLength":32,"maxLength":44},"slippageBps":{"type":"integer"}}}}}},"trade_SolanaSubmission":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletAddress","signature"],"properties":{"walletAddress":{"type":"string","minLength":32,"maxLength":44},"signature":{"type":"string","minLength":80,"maxLength":90}}}}}}}},"tags":[{"name":"meta"},{"name":"routing"},{"name":"rwa","description":"rwa service (proxied at /v1/rwa/*)"},{"name":"trade","description":"trade service (proxied at /v1/trade/*)"},{"name":"world-street-vault","description":"world-street-vault service (proxied at /v1/world-street-vault/*)"},{"name":"perp","description":"perp service (proxied at /v1/perp/*)"},{"name":"chess","description":"chess service (proxied at /v1/chess/*)"},{"name":"gas-sponsor","description":"gas-sponsor service (proxied at /v1/gas-sponsor/*)"},{"name":"earn","description":"earn service (proxied at /v1/earn/*)"},{"name":"kash","description":"kash service (proxied at /v1/kash/*)"},{"name":"ramping","description":"ramping service (proxied at /v1/ramping/*)"},{"name":"prediction-market","description":"prediction-market service (proxied at /v1/prediction-market/*)"},{"name":"market-square","description":"market-square service (proxied at /v1/market-square/*)"},{"name":"user-management","description":"user-management service (proxied at /v1/user-management/*)"}]}