{"openapi":"3.1.0","info":{"title":"Battlemat API","description":"API server for battlemat.app","version":"0.42.0"},"paths":{"/skill.md":{"get":{"summary":"Get Api Skill Markdown","description":"Return the public API skill markdown for AI agents.","operationId":"get_api_skill_markdown_skill_md_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/games":{"post":{"summary":"Create Game","description":"Create a new game associated with the authenticated user and return its details","operationId":"create_game_games_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Game"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}":{"get":{"summary":"Get Game","description":"Get an existing game by ID (requires game access)","operationId":"get_game_games__game_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Game"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Game","description":"Delete a game by ID (DM only)","operationId":"delete_game_games__game_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/mats":{"post":{"summary":"Create Mat","description":"Create a new mat for a game (DM only)","operationId":"create_mat_games__game_id__mats_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}},{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}},{"name":"rows","in":"query","required":false,"schema":{"type":"integer","default":48,"title":"Rows"}},{"name":"columns","in":"query","required":false,"schema":{"type":"integer","default":48,"title":"Columns"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mat"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Mats","description":"List all mats for a game (requires game access)","operationId":"list_mats_games__game_id__mats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Mat"},"title":"Response List Mats Games  Game Id  Mats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mats/{mat_id}":{"get":{"summary":"Get Mat","description":"Get a mat by ID (requires game access)","operationId":"get_mat_mats__mat_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mat"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Mat","description":"Delete a mat by ID (DM only)","operationId":"delete_mat_mats__mat_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Put Mat Data","description":"Replace the entire mat data dict (DM only).","operationId":"put_mat_data_mats__mat_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mat"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch Mat Data","description":"Apply a JSON Patch (RFC 6902) to canonical mat state.","operationId":"patch_mat_data_mats__mat_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Match"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mat"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users":{"post":{"summary":"Create User","description":"Create a new user and return their details including UUID.\nIf user already exists, returns the existing user to prevent email enumeration.","operationId":"create_user_users_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/me":{"get":{"summary":"Get Current User Profile","description":"Get the authenticated user's profile, including server-computed admin status.","operationId":"get_current_user_profile_users_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentUserProfile"}}}}},"security":[{"HTTPBearer":[]}]}},"/users/{user_id}":{"get":{"summary":"Get User","description":"Get user by ID (authenticate) - user can only access their own data","operationId":"get_user_users__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete User","description":"Delete a user by ID - user can only delete their own account","operationId":"delete_user_users__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/me/subscription":{"get":{"summary":"Get My Subscription","description":"Get the authenticated user's subscription state.","operationId":"get_my_subscription_users_me_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/users/{user_id}/games":{"get":{"summary":"List User Games","description":"List all games for a specific user - user can only access their own games","operationId":"list_user_games_users__user_id__games_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Game"},"title":"Response List User Games Users  User Id  Games Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/players":{"post":{"summary":"Add Player To Game","description":"Add a player (user) to a game by their UUID (DM only)","operationId":"add_player_to_game_games__game_id__players_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}},{"name":"player_id","in":"query","required":true,"schema":{"type":"string","title":"Player Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameAccess"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Game Players","description":"List all players that have access to a game - requires game access","operationId":"list_game_players_games__game_id__players_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"},"title":"Response List Game Players Games  Game Id  Players Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/players/{player_id}":{"delete":{"summary":"Remove Player From Game","description":"Remove a player's access to a game (DM only)","operationId":"remove_player_from_game_games__game_id__players__player_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}},{"name":"player_id","in":"path","required":true,"schema":{"type":"string","title":"Player Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/{user_id}/accessible-games":{"get":{"summary":"List Accessible Games","description":"List all games a user can access (both owned and shared) with DM names - user can only access their own accessible games","operationId":"list_accessible_games_users__user_id__accessible_games_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Game"},"title":"Response List Accessible Games Users  User Id  Accessible Games Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/{user_id}/assets":{"get":{"summary":"List User Assets","description":"List all assets owned by a user - user can only access their own assets","operationId":"list_user_assets_users__user_id__assets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Asset"},"title":"Response List User Assets Users  User Id  Assets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/active-mat/{mat_id}":{"put":{"summary":"Set Active Mat","description":"Set a mat as the active mat for a game (DM only)","operationId":"set_active_mat_games__game_id__active_mat__mat_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}},{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/invite":{"get":{"summary":"Get Game Invite Info","description":"Get public information about a game for invite purposes (no authentication required)","operationId":"get_game_invite_info_games__game_id__invite_get","parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameInviteInfo"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/join":{"post":{"summary":"Join Game","description":"Allow an authenticated user to join a game themselves","operationId":"join_game_games__game_id__join_post","parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinGameRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GameAccess"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/assets":{"post":{"summary":"Upload Asset","description":"Upload a new image asset to a game","operationId":"upload_asset_games__game_id__assets_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}},{"name":"mat_id","in":"query","required":false,"schema":{"type":"string","title":"Mat Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_asset_games__game_id__assets_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Game Assets","description":"List all assets for a game - requires game access","operationId":"list_game_assets_games__game_id__assets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Asset"},"title":"Response List Game Assets Games  Game Id  Assets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/assets":{"post":{"summary":"Upload Personal Asset","description":"Upload a new image asset not associated with any game (user-owned asset).","operationId":"upload_personal_asset_assets_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_personal_asset_assets_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/assets/generate":{"post":{"summary":"Generate Asset","description":"Generate an AI image asset from a text prompt.\n\nThe image generation runs asynchronously in the background.\nReturns immediately with an asset that has generation_status=\"pending\".\nThe client can poll GET /assets/{asset_id} to check progress.\n\nOnce complete, generation_status will be \"completed\" and cdn_url will be set.\nIf generation fails, generation_status will be \"failed\" and generation_error\nwill contain the error message.\n\nRate limited to 100 AI requests per user per calendar month.","operationId":"generate_asset_assets_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/assets/{asset_id}/edit":{"post":{"summary":"Edit Asset Image","description":"Create a non-destructive AI edit of an existing image asset.\n\nThe source image is left untouched. The edited image is created as a new\npending asset in the same scope and can be polled via GET /assets/{asset_id}.\nEdits count against the same monthly quota as other AI requests.","operationId":"edit_asset_image_assets__asset_id__edit_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/me/image-generation-usage":{"get":{"summary":"Get Image Generation Usage","description":"Get the current user's AI request usage for the current month.\n\nReturns:\n    - used: Number of AI requests this month\n    - limit: Maximum AI requests allowed per month (100)\n    - resets_at: When the limit resets (first of next month, midnight UTC)","operationId":"get_image_generation_usage_users_me_image_generation_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationQuota"}}}}},"security":[{"HTTPBearer":[]}]}},"/assets/{asset_id}":{"get":{"summary":"Get Asset Metadata","description":"Get asset metadata (without binary data) - requires game access","operationId":"get_asset_metadata_assets__asset_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Rename Asset","description":"Rename an asset.\n\n- Personal assets can only be renamed by their owner.\n- Game assets can be renamed by the game owner (DM) or the asset owner.","operationId":"rename_asset_assets__asset_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetRenameRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Asset","description":"Delete an asset.\n\n- If the asset is associated with a game, the game owner (DM) or the asset owner can delete it.\n- If the asset is not associated with any game, only the asset owner can delete it.","operationId":"delete_asset_assets__asset_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/assets/{asset_id}/data":{"get":{"summary":"Get Asset Data","description":"Get the binary image data for an asset - requires game access","operationId":"get_asset_data_assets__asset_id__data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mats/{mat_id}/background/{asset_id}":{"put":{"summary":"Set Mat Background","description":"Set an asset as the background for a mat (DM only)","operationId":"set_mat_background_mats__mat_id__background__asset_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}},{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mats/{mat_id}/background":{"delete":{"summary":"Remove Mat Background","description":"Remove the background asset from a mat (DM only)","operationId":"remove_mat_background_mats__mat_id__background_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"path","required":true,"schema":{"type":"string","title":"Mat Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/games/{game_id}/rolls":{"post":{"summary":"Create Roll","description":"Create a new roll log entry for a game (requires game access and user must match)","operationId":"create_roll_games__game_id__rolls_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRollLogEntry"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollLogEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Rolls","description":"Get roll log entries for a game (requires game access)","operationId":"get_rolls_games__game_id__rolls_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"game_id","in":"path","required":true,"schema":{"type":"string","title":"Game Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RollLogEntry"},"title":"Response Get Rolls Games  Game Id  Rolls Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens":{"post":{"summary":"Create Token","description":"Create a new token (library token if no mat_id, mat token if mat_id provided)","operationId":"create_token_tokens_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mat_id","in":"query","required":false,"schema":{"type":"string","title":"Mat Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens/{token_id}":{"get":{"summary":"Get Token","description":"Get token metadata (handles both library and mat tokens)","operationId":"get_token_tokens__token_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Update Token","description":"Update token metadata","operationId":"update_token_tokens__token_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Token","description":"Delete token","operationId":"delete_token_tokens__token_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/{user_id}/tokens":{"get":{"summary":"List User Library Tokens","description":"List library tokens (mat_id is null)","operationId":"list_user_library_tokens_users__user_id__tokens_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Token"},"title":"Response List User Library Tokens Users  User Id  Tokens Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens/{token_id}/rolls":{"get":{"summary":"Get Token Rolls","description":"Get all rolls associated with a token","operationId":"get_token_rolls_tokens__token_id__rolls_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RollAction"},"title":"Response Get Token Rolls Tokens  Token Id  Rolls Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens/{token_id}/rolls/{roll_id}":{"delete":{"summary":"Delete Token Roll","description":"Delete a specific roll associated with a token","operationId":"delete_token_roll_tokens__token_id__rolls__roll_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}},{"name":"roll_id","in":"path","required":true,"schema":{"type":"string","title":"Roll Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/email":{"post":{"summary":"Request Email Login","description":"Send login link to user's email","operationId":"request_email_login_auth_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/login":{"post":{"summary":"Login With Token","description":"Exchange email token for access/refresh tokens","operationId":"login_with_token_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/refresh":{"post":{"summary":"Refresh Access Token","description":"Exchange refresh token for new access/refresh tokens","operationId":"refresh_access_token_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Asset":{"properties":{"id":{"type":"string","title":"Id"},"filename":{"type":"string","title":"Filename"},"file_type":{"type":"string","title":"File Type"},"size_bytes":{"type":"integer","title":"Size Bytes"},"cdn_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cdn Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"game_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Game Id"},"mat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mat Id"},"owner_id":{"type":"string","title":"Owner Id"},"generation_status":{"anyOf":[{"type":"string","enum":["pending","generating","completed","failed"]},{"type":"null"}],"title":"Generation Status"},"generation_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generation Error"}},"type":"object","required":["id","filename","file_type","size_bytes","created_at","owner_id"],"title":"Asset"},"AssetRenameRequest":{"properties":{"filename":{"type":"string","maxLength":255,"minLength":1,"title":"Filename"}},"type":"object","required":["filename"],"title":"AssetRenameRequest"},"Body_upload_asset_games__game_id__assets_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_asset_games__game_id__assets_post"},"Body_upload_personal_asset_assets_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_personal_asset_assets_post"},"CreateRollLogEntry":{"properties":{"user_id":{"type":"string","title":"User Id"},"username":{"type":"string","title":"Username"},"roll_expression":{"type":"string","title":"Roll Expression"},"result":{"type":"integer","title":"Result"}},"type":"object","required":["user_id","username","roll_expression","result"],"title":"CreateRollLogEntry"},"CreateUserRequest":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["name","email"],"title":"CreateUserRequest"},"CurrentUserProfile":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_active":{"type":"string","format":"date-time","title":"Last Active"},"is_admin":{"type":"boolean","title":"Is Admin","default":false}},"type":"object","required":["id","name","email","created_at","last_active"],"title":"CurrentUserProfile"},"EmailLoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"redirect":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect"}},"type":"object","required":["email"],"title":"EmailLoginRequest"},"Game":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user_id":{"type":"string","title":"User Id"},"user_name":{"type":"string","title":"User Name"},"active_mat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Mat Id"}},"type":"object","required":["id","name","created_at","user_id","user_name"],"title":"Game"},"GameAccess":{"properties":{"user_id":{"type":"string","title":"User Id"},"game_id":{"type":"string","title":"Game Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["user_id","game_id","created_at"],"title":"GameAccess"},"GameInviteInfo":{"properties":{"game_id":{"type":"string","title":"Game Id"},"game_name":{"type":"string","title":"Game Name"},"dm_name":{"type":"string","title":"Dm Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"player_count":{"type":"integer","title":"Player Count"}},"type":"object","required":["game_id","game_name","dm_name","created_at","player_count"],"title":"GameInviteInfo"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageEditRequest":{"properties":{"prompt":{"type":"string","maxLength":4000,"minLength":1,"title":"Prompt"},"size":{"type":"string","enum":["1024x1024","1024x1536","1536x1024"],"title":"Size","default":"1024x1024"},"quality":{"type":"string","enum":["low","medium","high"],"title":"Quality","default":"low"}},"type":"object","required":["prompt"],"title":"ImageEditRequest"},"ImageGenerationQuota":{"properties":{"used":{"type":"integer","title":"Used"},"limit":{"type":"integer","title":"Limit","default":100},"resets_at":{"type":"string","format":"date-time","title":"Resets At"}},"type":"object","required":["used","resets_at"],"title":"ImageGenerationQuota","description":"User's monthly AI request usage and limits."},"ImageGenerationRequest":{"properties":{"prompt":{"type":"string","maxLength":4000,"minLength":1,"title":"Prompt"},"size":{"type":"string","enum":["1024x1024","1024x1536","1536x1024"],"title":"Size","default":"1024x1024"},"quality":{"type":"string","enum":["low","medium","high"],"title":"Quality","default":"low"}},"type":"object","required":["prompt"],"title":"ImageGenerationRequest"},"JoinGameRequest":{"properties":{"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["user_id"],"title":"JoinGameRequest"},"LoginRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"LoginRequest"},"LoginResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"user_id":{"type":"string","title":"User Id"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["access_token","refresh_token","user_id","expires_in"],"title":"LoginResponse"},"Mat":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"game_id":{"type":"string","title":"Game Id"},"data":{"additionalProperties":true,"type":"object","title":"Data"},"background_asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Background Asset Id"}},"type":"object","required":["id","name","created_at","game_id"],"title":"Mat"},"MatUpdate":{"properties":{"data":{"additionalProperties":true,"type":"object","title":"Data"}},"type":"object","required":["data"],"title":"MatUpdate"},"RollAction":{"properties":{"name":{"type":"string","title":"Name","description":"Concise, descriptive name (e.g. 'Melee attack (Longsword)')"},"num_dice":{"type":"integer","minimum":1.0,"title":"Num Dice","description":"Number of dice to roll"},"dice_type":{"type":"integer","enum":[2,3,4,6,8,10,12,20,100],"title":"Dice Type","description":"Sides of the dice"},"modifier":{"type":"integer","title":"Modifier","description":"The modifier to the roll","default":0}},"type":"object","required":["name","num_dice","dice_type"],"title":"RollAction","description":"A single roll action extracted from a stat block."},"RollLogEntry":{"properties":{"id":{"type":"integer","title":"Id"},"game_id":{"type":"string","title":"Game Id"},"user_id":{"type":"string","title":"User Id"},"username":{"type":"string","title":"Username"},"roll_expression":{"type":"string","title":"Roll Expression"},"result":{"type":"integer","title":"Result"},"message":{"type":"string","title":"Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","game_id","user_id","username","roll_expression","result","message","created_at"],"title":"RollLogEntry"},"SubscriptionStatusResponse":{"properties":{"tier":{"type":"integer","title":"Tier"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"billing_interval":{"anyOf":[{"type":"string","enum":["month","year"]},{"type":"null"}],"title":"Billing Interval"},"is_active":{"type":"boolean","title":"Is Active"},"cancel_at_period_end":{"type":"boolean","title":"Cancel At Period End","default":false},"current_period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Current Period End"},"can_manage_billing":{"type":"boolean","title":"Can Manage Billing","default":false},"can_cancel_subscription":{"type":"boolean","title":"Can Cancel Subscription","default":false}},"type":"object","required":["tier","is_active"],"title":"SubscriptionStatusResponse"},"Token":{"properties":{"id":{"type":"string","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user_id":{"type":"string","title":"User Id"},"game_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Game Id"},"mat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mat Id"},"entity_type":{"type":"string","title":"Entity Type"},"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"hidden":{"type":"boolean","title":"Hidden","default":false},"asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Asset Id"},"source_token_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Token Id"},"initiative_modifier":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Initiative Modifier"},"hit_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hit Points"}},"type":"object","required":["id","created_at","user_id","entity_type"],"title":"Token"},"TokenCreate":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"entity_type":{"type":"string","title":"Entity Type"},"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"hidden":{"type":"boolean","title":"Hidden","default":false},"asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Asset Id"},"source_token_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Token Id"},"initiative_modifier":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Initiative Modifier"},"hit_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hit Points"}},"type":"object","required":["entity_type"],"title":"TokenCreate"},"TokenUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"hidden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hidden"},"asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Asset Id"},"source_token_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Token Id"},"initiative_modifier":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Initiative Modifier"},"hit_points":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hit Points"}},"type":"object","title":"TokenUpdate"},"User":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_active":{"type":"string","format":"date-time","title":"Last Active"}},"type":"object","required":["id","name","email","created_at","last_active"],"title":"User"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}