{ "openapi": "3.0.1", "info": { "title": "RpgRoller API", "version": "1.0.0" }, "paths": { "/api/health": { "get": { "operationId": "getHealth", "responses": { "200": { "description": "API is reachable.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } } } }, "/api/rulesets": { "get": { "operationId": "getRulesets", "responses": { "200": { "description": "Supported rulesets.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/RulesetDefinition" } } } } } } } }, "/api/auth/register": { "post": { "operationId": "registerUser", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRequest" } } } }, "responses": { "200": { "description": "Registered user.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } } } } }, "/api/auth/login": { "post": { "operationId": "loginUser", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } } }, "responses": { "200": { "description": "Logged-in user.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } } } } }, "/api/auth/logout": { "post": { "operationId": "logoutUser", "responses": { "204": { "description": "Logged out." } } } }, "/api/me": { "get": { "operationId": "getMe", "responses": { "200": { "description": "Current user context.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MeResponse" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/campaigns": { "get": { "operationId": "getCampaigns", "responses": { "200": { "description": "Accessible campaigns.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CampaignSummary" } } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } }, "post": { "operationId": "createCampaign", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateCampaignRequest" } } } }, "responses": { "200": { "description": "Created campaign.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CampaignSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/campaigns/{campaignId}": { "get": { "operationId": "getCampaign", "parameters": [ { "name": "campaignId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Campaign details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CampaignDetails" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/campaigns/{campaignId}/log": { "get": { "operationId": "getCampaignLog", "parameters": [ { "name": "campaignId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Campaign log entries.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CampaignLogEntry" } } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/characters": { "post": { "operationId": "createCharacter", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateCharacterRequest" } } } }, "responses": { "200": { "description": "Created character.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CharacterSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/characters/{characterId}": { "put": { "operationId": "updateCharacter", "parameters": [ { "name": "characterId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateCharacterRequest" } } } }, "responses": { "200": { "description": "Updated character.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CharacterSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/characters/{characterId}/activate": { "post": { "operationId": "activateCharacter", "parameters": [ { "name": "characterId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "Activation succeeded.", "content": { "application/json": { "schema": { "type": "boolean" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/characters": { "get": { "operationId": "getOwnCharacters", "responses": { "200": { "description": "Characters owned by the user.", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CharacterSummary" } } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/characters/{characterId}/skills": { "post": { "operationId": "createSkill", "parameters": [ { "name": "characterId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateSkillRequest" } } } }, "responses": { "200": { "description": "Created skill.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/skills/{skillId}": { "put": { "operationId": "updateSkill", "parameters": [ { "name": "skillId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSkillRequest" } } } }, "responses": { "200": { "description": "Updated skill.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SkillSummary" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } }, "/api/skills/{skillId}/roll": { "post": { "operationId": "rollSkill", "parameters": [ { "name": "skillId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RollSkillRequest" } } } }, "responses": { "200": { "description": "Roll result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RollResult" } } } }, "400": { "description": "Validation error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "401": { "description": "Unauthorized." } } } } }, "components": { "schemas": { "HealthResponse": { "type": "object", "properties": { "status": { "type": "string" } }, "required": [ "status" ] }, "ApiError": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] }, "RegisterRequest": { "type": "object", "properties": { "username": { "type": "string" }, "password": { "type": "string" }, "displayName": { "type": "string" } }, "required": [ "username", "password", "displayName" ] }, "LoginRequest": { "type": "object", "properties": { "username": { "type": "string" }, "password": { "type": "string" } }, "required": [ "username", "password" ] }, "UserSummary": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "username": { "type": "string" }, "displayName": { "type": "string" } }, "required": [ "id", "username", "displayName" ] }, "MeResponse": { "type": "object", "properties": { "user": { "$ref": "#/components/schemas/UserSummary" }, "activeCharacterId": { "type": "string", "format": "uuid", "nullable": true }, "currentCampaignId": { "type": "string", "format": "uuid", "nullable": true } }, "required": [ "user" ] }, "RulesetDefinition": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "diceSyntax": { "type": "string" } }, "required": [ "id", "name", "diceSyntax" ] }, "CreateCampaignRequest": { "type": "object", "properties": { "name": { "type": "string" }, "rulesetId": { "type": "string" } }, "required": [ "name", "rulesetId" ] }, "CampaignSummary": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "rulesetId": { "type": "string" }, "gmUserId": { "type": "string", "format": "uuid" } }, "required": [ "id", "name", "rulesetId", "gmUserId" ] }, "CampaignDetails": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "rulesetId": { "type": "string" }, "gm": { "$ref": "#/components/schemas/UserSummary" }, "characters": { "type": "array", "items": { "$ref": "#/components/schemas/CharacterSummary" } }, "skills": { "type": "array", "items": { "$ref": "#/components/schemas/SkillSummary" } } }, "required": [ "id", "name", "rulesetId", "gm", "characters", "skills" ] }, "CreateCharacterRequest": { "type": "object", "properties": { "name": { "type": "string" }, "campaignId": { "type": "string", "format": "uuid" } }, "required": [ "name", "campaignId" ] }, "UpdateCharacterRequest": { "type": "object", "properties": { "name": { "type": "string" }, "campaignId": { "type": "string", "format": "uuid" } }, "required": [ "name", "campaignId" ] }, "CharacterSummary": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "ownerUserId": { "type": "string", "format": "uuid" }, "campaignId": { "type": "string", "format": "uuid" } }, "required": [ "id", "name", "ownerUserId", "campaignId" ] }, "CreateSkillRequest": { "type": "object", "properties": { "name": { "type": "string" }, "diceRollDefinition": { "type": "string" }, "wildDice": { "type": "integer", "format": "int32" }, "allowFumble": { "type": "boolean" }, "skillGroupId": { "type": "string", "format": "uuid", "nullable": true }, "fumbleRange": { "type": "integer", "format": "int32", "nullable": true } }, "required": [ "name", "diceRollDefinition", "wildDice", "allowFumble" ] }, "UpdateSkillRequest": { "type": "object", "properties": { "name": { "type": "string" }, "diceRollDefinition": { "type": "string" }, "wildDice": { "type": "integer", "format": "int32" }, "allowFumble": { "type": "boolean" }, "skillGroupId": { "type": "string", "format": "uuid", "nullable": true }, "fumbleRange": { "type": "integer", "format": "int32", "nullable": true } }, "required": [ "name", "diceRollDefinition", "wildDice", "allowFumble" ] }, "SkillSummary": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "characterId": { "type": "string", "format": "uuid" }, "skillGroupId": { "type": "string", "format": "uuid", "nullable": true }, "name": { "type": "string" }, "diceRollDefinition": { "type": "string" }, "wildDice": { "type": "integer", "format": "int32" }, "allowFumble": { "type": "boolean" }, "fumbleRange": { "type": "integer", "format": "int32", "nullable": true } }, "required": [ "id", "characterId", "name", "diceRollDefinition", "wildDice", "allowFumble" ] }, "RollSkillRequest": { "type": "object", "properties": { "visibility": { "type": "string" } }, "required": [ "visibility" ] }, "RollDieResult": { "type": "object", "properties": { "roll": { "type": "integer", "format": "int32" }, "crit": { "type": "boolean" }, "fumble": { "type": "boolean" }, "wild": { "type": "boolean" }, "removed": { "type": "boolean" }, "added": { "type": "boolean" }, "sequence": { "type": "integer", "format": "int32", "nullable": true }, "kind": { "type": "string", "nullable": true }, "signedContribution": { "type": "integer", "format": "int32", "nullable": true } }, "required": [ "roll", "crit", "fumble", "wild", "removed", "added" ] }, "RollResult": { "type": "object", "properties": { "rollId": { "type": "string", "format": "uuid" }, "campaignId": { "type": "string", "format": "uuid" }, "characterId": { "type": "string", "format": "uuid" }, "skillId": { "type": "string", "format": "uuid" }, "rollerUserId": { "type": "string", "format": "uuid" }, "visibility": { "type": "string" }, "result": { "type": "integer", "format": "int32" }, "breakdown": { "type": "string" }, "dice": { "type": "array", "items": { "$ref": "#/components/schemas/RollDieResult" } }, "timestampUtc": { "type": "string", "format": "date-time" } }, "required": [ "rollId", "campaignId", "characterId", "skillId", "rollerUserId", "visibility", "result", "breakdown", "dice", "timestampUtc" ] }, "CampaignLogEntry": { "type": "object", "properties": { "rollId": { "type": "string", "format": "uuid" }, "campaignId": { "type": "string", "format": "uuid" }, "characterId": { "type": "string", "format": "uuid" }, "skillId": { "type": "string", "format": "uuid" }, "rollerUserId": { "type": "string", "format": "uuid" }, "visibility": { "type": "string" }, "result": { "type": "integer", "format": "int32" }, "breakdown": { "type": "string" }, "timestampUtc": { "type": "string", "format": "date-time" } }, "required": [ "rollId", "campaignId", "characterId", "skillId", "rollerUserId", "visibility", "result", "breakdown", "timestampUtc" ] } } } }