{"openapi":"3.1.0","info":{"title":"Tailorgame API","version":"1.0.0","description":"Discover browser skill games and read community practice rankings without authentication. Account actions require the user’s existing Firebase-authenticated Tailorgame browser session. Tailorgame does not offer delegated OAuth, API keys, payment checkout, or agent access to private account data through MCP. Review /auth.md before using account endpoints."},"servers":[{"url":"https://tailorgame.com"}],"externalDocs":{"url":"https://tailorgame.com/docs","description":"Integration guide, examples, authentication, limits, and MCP tools."},"tags":[{"name":"Public","description":"No account or credentials required."},{"name":"Account","description":"User-controlled, same-origin authenticated browser actions."},{"name":"Authentication","description":"Existing Firebase browser sign-in; not a delegated OAuth authorization server."},{"name":"MCP","description":"Public read-only JSON-RPC tools and documentation resources."}],"x-agent-capabilities":{"publicReads":["GET /api/games","GET /api/rankings"],"documentation":"/docs","openapi":"/openapi.json","mcp":{"endpoint":"/mcp","access":"public-read-only","protocolVersion":"2025-11-25"},"authentication":{"accountActions":"Firebase-authenticated HTTP-only session cookie","delegatedOAuth":false,"apiKeys":false},"limitations":["Practice scores are client-reported.","Rooms persist membership without synchronizing gameplay.","Payment checkout is not connected.","Generation is available only when configured and requires a reviewed server quote."]},"paths":{"/api/games":{"get":{"operationId":"listGames","summary":"List the public game catalog","tags":["Public"],"security":[{},{"sessionCookie":[]}],"description":"Without a session, returns public starter and community games, including coming-soon entries. With a verified session, also includes the player’s accessible private games and love state. Read status before offering to play. Responses are private and uncached.","responses":{"200":{"description":"Visible games.","content":{"application/json":{"schema":{"type":"object","properties":{"games":{"type":"array","items":{"$ref":"#/components/schemas/Game"}}},"required":["games"]}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createTemplateGame","summary":"Create a bowling or memory template game for 20 demo credits","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":3,"maxLength":60},"description":{"type":"string","minLength":10,"maxLength":500},"template":{"type":"string","enum":["bowling","memory"]},"visibility":{"type":"string","enum":["private","public"],"default":"private"},"accent":{"type":"string","pattern":"^(violet|rose|#[0-9a-fA-F]{6})$"}},"required":["name","description","template"]}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"201":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"game":{"$ref":"#/components/schemas/Game"},"profile":{"$ref":"#/components/schemas/Profile"}},"required":["game","profile"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/rankings":{"get":{"operationId":"getRankings","summary":"Read all-time public practice rankings","tags":["Public"],"security":[],"description":"Up to 20 entries per list. Repeat sessions do not increase distinct-player counts. Ties share ranks; raw practice scores across games are not verified competition results. Returns public display names and statistics, excluding email, birthday, authentication metadata, and credit balances.","responses":{"200":{"description":"Public game and player ranking lists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Rankings"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/players/{id}":{"get":{"operationId":"getPublicPlayerProfile","summary":"Read a player profile only if the player opted into public sharing","tags":["Public"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1},"description":"Owned or accessible resource ID."}],"responses":{"200":{"description":"Opt-in public profile; excludes birthday, email, auth metadata, and balances.","content":{"application/json":{"schema":{"type":"object","properties":{"profile":{"$ref":"#/components/schemas/PublicProfile"}},"required":["profile"]}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/profile":{"get":{"operationId":"getMyProfile","summary":"Read the current player’s profile, latest 50 scores, and credit entries","tags":["Account"],"security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Account-private response; never store in a shared cache.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileResponse"}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateMyProfile","summary":"Update the current player’s editable profile","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilePatch"}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"200":{"description":"Operation completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileResponse"}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/scores":{"post":{"operationId":"savePracticeScore","summary":"Record one completed client-reported practice result","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gameId":{"type":"string","minLength":1,"maxLength":100},"score":{"type":"integer","minimum":0,"maximum":100000}},"required":["gameId","score"]}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"201":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"score":{"$ref":"#/components/schemas/Score"},"profile":{"$ref":"#/components/schemas/Profile"}},"required":["score","profile"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/games/love":{"post":{"operationId":"setGameLove","summary":"Set or remove the current player’s love for a playable game","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gameId":{"type":"string"},"loved":{"type":"boolean"}},"required":["gameId","loved"]}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"200":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"gameId":{"type":"string"},"loved":{"type":"boolean"},"loveCount":{"type":"integer","minimum":0}},"required":["gameId","loved","loveCount"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/rooms":{"get":{"operationId":"listMyRooms","summary":"List rooms the current player belongs to","tags":["Account"],"security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Account-private response; never store in a shared cache.","content":{"application/json":{"schema":{"type":"object","properties":{"rooms":{"type":"array","items":{"$ref":"#/components/schemas/Room"}}},"required":["rooms"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createRoom","summary":"Create a room with capacity for four members","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gameId":{"type":"string"},"name":{"type":"string"}},"required":["gameId"]}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"201":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"room":{"$ref":"#/components/schemas/Room"}},"required":["room"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/rooms/join":{"post":{"operationId":"joinRoom","summary":"Join a room using its invitation code","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":6,"maxLength":6}},"required":["code"]}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"200":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"room":{"$ref":"#/components/schemas/Room"}},"required":["room"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/game-briefs":{"get":{"operationId":"listMyGameBriefs","summary":"List the current player’s private game design drafts","tags":["Account"],"security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Account-private response; never store in a shared cache.","content":{"application/json":{"schema":{"type":"object","properties":{"briefs":{"type":"array","items":{"$ref":"#/components/schemas/GameBrief"}}},"required":["briefs"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"saveGameBrief","summary":"Create or update an owned private draft without spending credits","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameBriefInput"}}}},"description":"Saving is free and does not create a playable game. Include an owned draft id to update. JSON object limit: 32,768 characters. Unknown or inaccessible IDs return 404.","responses":{"200":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"brief":{"$ref":"#/components/schemas/GameBrief"}},"required":["brief"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/generations":{"get":{"operationId":"listMyGenerationJobs","summary":"Read the current player’s generation jobs and feature availability","tags":["Account"],"security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Account-private response; never store in a shared cache.","content":{"application/json":{"schema":{"type":"object","properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/GenerationJob"}},"configuration":{"type":"object","additionalProperties":true},"pricing":{"type":"object","additionalProperties":true}},"required":["jobs","configuration","pricing"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createGenerationJob","summary":"Reserve the reviewed quote budget and request a private playable prototype","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"briefId":{"type":"string"},"requestId":{"type":"string","description":"Client-generated stable request ID. Reuse to recover an unknown outcome instead of creating another paid job."},"quoteId":{"type":"string","description":"ID from the reviewed, unexpired server quote."}},"required":["briefId","requestId","quoteId"]}}}},"description":"Requires generation to be configured, a saved owned brief, available credits, and an unexpired server quote. Show the quote and obtain the user’s choice before reserving credits. Consumed model usage can be charged even for unsuccessful attempts; unused reservation is released. Repeat the same requestId to recover an unknown result safely. Never automatically retry with a new requestId.","responses":{"202":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/GenerationJob"}},"required":["job"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/generations/quote":{"post":{"operationId":"quoteGeneration","summary":"Get a server-priced generation quote without reserving credits","tags":["Account"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"briefId":{"type":"string"}},"required":["briefId"]}}}},"description":"Use only in the user’s signed-in Tailorgame browser session. JSON object limit: 8,192 characters, except game briefs (32,768). User-owned resource access is checked on the server.","responses":{"200":{"description":"Operation completed.","content":{"application/json":{"schema":{"type":"object","properties":{"quote":{"$ref":"#/components/schemas/GenerationQuote"},"balance":{"type":"integer","minimum":0}},"required":["quote","balance"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/generations/{id}":{"get":{"operationId":"getMyGenerationJob","summary":"Read and reconcile an owned generation job","tags":["Account"],"security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Account-private response; never store in a shared cache.","content":{"application/json":{"schema":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/GenerationJob"}},"required":["job"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1},"description":"Owned or accessible resource ID."}]}},"/api/games/{id}/artifact":{"get":{"operationId":"getGeneratedArtifact","summary":"Read a generated game artifact when ownership or room access allows it","tags":["Account"],"security":[{"sessionCookie":[]}],"responses":{"200":{"description":"Account-private response; never store in a shared cache.","content":{"application/json":{"schema":{"type":"object","properties":{"game":{"$ref":"#/components/schemas/Game"},"artifact":{"$ref":"#/components/schemas/GeneratedArtifact"}},"required":["game","artifact"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1},"description":"Owned or accessible resource ID."}]}},"/api/auth/config":{"get":{"operationId":"getBrowserAuthConfiguration","summary":"Read allowlisted public Firebase browser configuration","tags":["Authentication"],"security":[],"responses":{"200":{"description":"Public web configuration, never administrative credentials.","content":{"application/json":{"schema":{"type":"object","properties":{"config":{"$ref":"#/components/schemas/FirebaseConfig"}},"required":["config"]}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/auth/csrf":{"get":{"operationId":"getSessionCsrfToken","summary":"Start same-origin browser session bootstrap","tags":["Authentication"],"security":[],"description":"Sets an HTTP-only tailorgame-csrf cookie. Keep the cookie and send the returned token as X-CSRF-Token for session POST and DELETE. Requests marked cross-site are rejected.","responses":{"200":{"description":"CSRF token and paired cookie.","content":{"application/json":{"schema":{"type":"object","properties":{"csrfToken":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"required":["csrfToken"]}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/auth/session":{"get":{"operationId":"getBrowserSession","summary":"Read the current browser session or null","tags":["Authentication"],"security":[{},{"sessionCookie":[]}],"responses":{"200":{"description":"Current user or null when signed out.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"anyOf":[{"$ref":"#/components/schemas/AuthUser"},{"type":"null"}]}},"required":["user"]}}}}}},"post":{"operationId":"createBrowserSession","summary":"Exchange a recently issued Firebase ID token for an HTTP-only session cookie","tags":["Authentication"],"security":[],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."},{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string","pattern":"^[0-9a-f]{64}$"},"description":"Token from GET /api/auth/csrf, paired with that response’s HTTP-only CSRF cookie."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"idToken":{"type":"string","minLength":20,"maxLength":12000,"writeOnly":true}},"required":["idToken"]}}}},"description":"The person signs in through the configured Firebase browser flow. The ID token must have auth_time within five minutes; email/password accounts must have verified email. Requires the paired CSRF cookie, token, and exact Origin. Maximum body: 16,384 bytes. Sets tailorgame-session for up to five days. This is not an OAuth authorization endpoint or machine-to-machine credential exchange.","responses":{"200":{"description":"Verified user and HTTP-only session cookie.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/AuthUser"}},"required":["user"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteBrowserSession","summary":"Sign out the current browser session","tags":["Authentication"],"security":[{"sessionCookie":[]}],"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string"},"description":"The exact Tailorgame browser origin. Cross-site account mutations are rejected."},{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string","pattern":"^[0-9a-f]{64}$"},"description":"Token from GET /api/auth/csrf, paired with that response’s HTTP-only CSRF cookie."}],"responses":{"200":{"description":"Session cookie expired.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"null"}},"required":["user"]}}}},"400":{"description":"Invalid JSON or input values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"A verified Tailorgame session is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Origin, CSRF, or account access check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource is missing or inaccessible to this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Insufficient credits, unavailable game, capacity, or request conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds the endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The operation could not be completed. Read the error before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service or feature is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mcp":{"post":{"operationId":"callPublicMcp","summary":"Use the public read-only Model Context Protocol interface","tags":["MCP"],"security":[],"description":"Streamable HTTP JSON-RPC endpoint, protocol version 2025-11-25. Supports initialize, ping, tools/list, tools/call, resources/list and resources/read. Tools: list_games({query?,category?,limit?}), get_rankings({}), get_documentation({topic?}). No account mutations or private account reads. Accept must include application/json and text/event-stream. Send MCP-Protocol-Version: 2025-11-25 after initialization. GET event streams are not offered.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","integer"],"description":"Required for requests; omit for notifications. Null IDs are invalid."},"method":{"type":"string"},"params":{"type":"object","additionalProperties":true}},"required":["jsonrpc","method"]}}}},"responses":{"200":{"description":"JSON-RPC result or protocol error. Tool execution failures are result objects with isError: true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}},"202":{"description":"Accepted notification; no response body."},"400":{"description":"Malformed JSON-RPC request or unsupported protocol version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"403":{"description":"Origin is not an authorized Tailorgame origin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"406":{"description":"Accept must list application/json and text/event-stream.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"413":{"description":"Request body exceeds 16,384 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"415":{"description":"Send Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}}}},"get":{"operationId":"getMcpTransportInformation","summary":"Reports that MCP SSE listening is not offered","tags":["MCP"],"security":[],"responses":{"400":{"description":"Unsupported MCP-Protocol-Version header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"403":{"description":"Origin is not an authorized Tailorgame origin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"405":{"description":"Use POST for JSON-RPC messages. This server does not offer an SSE listener.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}}}}}},"components":{"securitySchemes":{"sessionCookie":{"type":"apiKey","in":"cookie","name":"tailorgame-session","description":"HTTP-only Firebase session established by the user’s browser sign-in. Account actions also enforce same-origin requests. There is no delegated OAuth or API-key access."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","description":"Optional stable authentication error code."}},"required":["error"]},"JsonRpcError":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","integer"],"description":"Omitted when the request ID could not be read."},"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"]}},"required":["jsonrpc","error"]},"JsonRpcResponse":{"oneOf":[{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","integer"]},"result":{"type":"object","additionalProperties":true}},"required":["jsonrpc","id","result"]},{"$ref":"#/components/schemas/JsonRpcError"}]},"Game":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["Arcade","Cards","Strategy","Racing"]},"template":{"type":["string","null"],"enum":["bowling","memory",null]},"engine":{"type":"string","const":"generated"},"generationId":{"type":"string"},"instructions":{"type":"string"},"image":{"type":"string"},"accent":{"type":"string"},"players":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["playable","coming-soon"]},"creator":{"type":"string"},"playCount":{"type":"integer","minimum":0},"uniquePlayerCount":{"type":"integer","minimum":0},"loveCount":{"type":"integer","minimum":0},"lovedByMe":{"type":"boolean"},"visibility":{"type":"string","enum":["public","private"]},"createdAt":{"type":"string"},"ownerId":{"type":"string"}},"required":["id","name","description","category","template","image","accent","players","tags","status","creator","playCount","visibility","createdAt"]},"RankedGame":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"image":{"type":"string"},"category":{"type":"string"},"uniquePlayerCount":{"type":"integer","minimum":0},"playCount":{"type":"integer","minimum":0},"loveCount":{"type":"integer","minimum":0},"rank":{"type":"integer","minimum":1}},"required":["id","name","image","category","uniquePlayerCount","playCount","loveCount","rank"]},"RankedPlayer":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"gamesPlayed":{"type":"integer","minimum":0},"bestScore":{"type":"integer","minimum":0},"rank":{"type":"integer","minimum":1}},"required":["id","name","gamesPlayed","bestScore","rank"]},"Rankings":{"type":"object","properties":{"mostPlayedGames":{"type":"array","items":{"$ref":"#/components/schemas/RankedGame"}},"mostLovedGames":{"type":"array","items":{"$ref":"#/components/schemas/RankedGame"}},"mostActivePlayers":{"type":"array","items":{"$ref":"#/components/schemas/RankedPlayer"}},"highestScoringPlayers":{"type":"array","items":{"$ref":"#/components/schemas/RankedPlayer"}}},"required":["mostPlayedGames","mostLovedGames","mostActivePlayers","highestScoringPlayers"]},"AuthUser":{"type":"object","properties":{"uid":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"picture":{"type":"string"},"providerIds":{"type":"array","items":{"type":"string"}}},"required":["uid","name"]},"FirebaseConfig":{"type":"object","properties":{"apiKey":{"type":"string"},"authDomain":{"type":"string"},"projectId":{"type":"string"},"appId":{"type":"string"},"providers":{"type":"array","items":{"type":"string"}},"messagingSenderId":{"type":"string"},"authEmulatorUrl":{"type":"string","description":"Development only."}},"required":["apiKey","authDomain","projectId","appId","providers"]},"Profile":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"picture":{"type":"string"},"providerIds":{"type":"array","items":{"type":"string"}},"fullName":{"type":"string"},"fullNameSource":{"type":"string","enum":["provider","custom"]},"bio":{"type":"string"},"birthday":{"type":"string","description":"Account-private."},"location":{"type":"string"},"hobbies":{"type":"array","items":{"type":"string"}},"favoriteGameTypes":{"type":"array","items":{"type":"string"}},"pronouns":{"type":"string"},"website":{"type":"string"},"profileVisibility":{"type":"string","enum":["private","public"]},"credits":{"type":"integer","minimum":0},"totalScore":{"type":"integer","minimum":0},"gamesPlayed":{"type":"integer","minimum":0},"bestScore":{"type":"integer","minimum":0},"createdGames":{"type":"integer","minimum":0},"createdAt":{"type":"string"}},"required":["id","name","credits","totalScore","gamesPlayed","bestScore","createdGames","createdAt"]},"ProfilePatch":{"type":"object","additionalProperties":false,"minProperties":1,"description":"Fields are trimmed before validation. Empty optional text clears it. Birthday stays account-private; website must be empty or an HTTPS URL without embedded credentials. Lists accept at most 12 nonempty items of at most 40 characters and are deduplicated.","properties":{"name":{"type":"string","minLength":2,"maxLength":30},"fullName":{"type":"string","maxLength":120},"bio":{"type":"string","maxLength":500},"birthday":{"type":"string","maxLength":10,"description":"Empty or a real, non-future YYYY-MM-DD date."},"location":{"type":"string","maxLength":100},"hobbies":{"type":"array","maxItems":12,"items":{"type":"string","minLength":1,"maxLength":40}},"favoriteGameTypes":{"type":"array","maxItems":12,"items":{"type":"string","minLength":1,"maxLength":40}},"pronouns":{"type":"string","maxLength":40},"website":{"type":"string","maxLength":200},"profileVisibility":{"type":"string","enum":["private","public"]}}},"PublicProfile":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"fullName":{"type":"string"},"picture":{"type":"string"},"bio":{"type":"string"},"location":{"type":"string"},"hobbies":{"type":"array","items":{"type":"string"}},"favoriteGameTypes":{"type":"array","items":{"type":"string"}},"pronouns":{"type":"string"},"website":{"type":"string"},"gamesPlayed":{"type":"integer","minimum":0},"createdGames":{"type":"integer","minimum":0},"createdAt":{"type":"string"}},"required":["id","name","gamesPlayed","createdGames","createdAt"]},"Score":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"gameId":{"type":"string"},"gameName":{"type":"string"},"score":{"type":"integer","minimum":0},"createdAt":{"type":"string"}},"required":["id","playerId","gameId","gameName","score","createdAt"]},"CreditEntry":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"type":"integer"},"reason":{"type":"string"},"gameId":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","playerId","amount","reason","createdAt"]},"ProfileResponse":{"type":"object","properties":{"profile":{"$ref":"#/components/schemas/Profile"},"scores":{"type":"array","items":{"$ref":"#/components/schemas/Score"}},"ledger":{"type":"array","items":{"$ref":"#/components/schemas/CreditEntry"}}},"required":["profile","scores","ledger"]},"Room":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"gameId":{"type":"string"},"gameName":{"type":"string"},"hostId":{"type":"string"},"members":{"type":"array","items":{"type":"object","properties":{"playerId":{"type":"string"},"name":{"type":"string"},"joinedAt":{"type":"string"}},"required":["playerId","name","joinedAt"]}},"capacity":{"type":"integer","minimum":1},"createdAt":{"type":"string"}},"required":["id","code","name","gameId","gameName","hostId","members","capacity","createdAt"]},"GameBriefInput":{"type":"object","properties":{"id":{"type":"string","description":"Include only when updating an owned draft."},"idea":{"type":"string","minLength":20,"maxLength":3000},"visualStyle":{"type":"string","minLength":10,"maxLength":1500},"dimensions":{"type":"string","minLength":2,"maxLength":1000},"mechanics":{"type":"string","minLength":20,"maxLength":3000},"scoring":{"type":"string","minLength":20,"maxLength":2000}},"required":["idea","visualStyle","dimensions","mechanics","scoring"]},"GameBrief":{"allOf":[{"$ref":"#/components/schemas/GameBriefInput"},{"type":"object","properties":{"id":{"type":"string"},"ownerId":{"type":"string"},"name":{"type":"string"},"prompt":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"status":{"type":"string","const":"draft"}},"required":["id","ownerId","name","prompt","createdAt","updatedAt","status"]}]},"GenerationJob":{"type":"object","properties":{"id":{"type":"string"},"ownerId":{"type":"string"},"briefId":{"type":"string"},"model":{"type":"string"},"reservedCredits":{"type":"integer","minimum":0},"chargedCredits":{"type":"integer","minimum":0},"releasedCredits":{"type":"integer","minimum":0},"actualCostMicros":{"type":"integer","minimum":0},"usageEstimated":{"type":"boolean"},"status":{"type":"string","enum":["queued","generating","ready","failed"]},"attempts":{"type":"integer","minimum":0},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"gameId":{"type":"string"},"error":{"type":"string"},"refunded":{"type":"boolean"}},"required":["id","ownerId","briefId","model","reservedCredits","status","attempts","createdAt","updatedAt"]},"GenerationQuote":{"type":"object","properties":{"id":{"type":"string"},"model":{"type":"string"},"projectId":{"type":"string"},"location":{"type":"string","enum":["eu","global"]},"reservedCredits":{"type":"integer","minimum":0},"maxCostUsd":{"type":"number","minimum":0},"creditValueUsd":{"type":"number","minimum":0},"targetMarginPercent":{"type":"number"},"expiresAt":{"type":"string"},"maxInputTokens":{"type":"integer","minimum":0},"maxOutputTokens":{"type":"integer","minimum":0},"maxAttempts":{"type":"integer","minimum":1},"priceVersion":{"type":"string"},"policy":{"type":"object","additionalProperties":true}},"required":["id","model","projectId","location","reservedCredits","maxCostUsd","creditValueUsd","targetMarginPercent","expiresAt","maxInputTokens","maxOutputTokens","maxAttempts","priceVersion","policy"]},"GeneratedArtifact":{"type":"object","properties":{"version":{"type":"integer","const":1},"title":{"type":"string"},"description":{"type":"string"},"instructions":{"type":"string"},"category":{"type":"string"},"accent":{"type":"string"},"code":{"type":"string","description":"Untrusted generated code; run only inside Tailorgame’s isolated player."}},"required":["version","title","description","instructions","category","accent","code"]}}}}