SystemStatus - API Spec (Phase 1)
SystemStatus β API Spec (Phase 1)
References: SystemStatus-PRD, SystemStatus - Concept & Features, SystemStatus - Research. All endpoints require JWT auth; role-based authorization enforced (SO/DM vs Player). JSON unless noted.
Conventions
- Base URL:
/api/v1 - Errors:
{ error: { code, message, details? } } - IDs: UUID strings
- Pagination:
?limit=50&cursor=...
Auth & Workspace
- POST
/auth/loginβ{ token, user } - GET
/workspacesβ list - POST
/workspaces(SO) β create - GET
/workspaces/{id}β details
Characters
- GET
/workspaces/{wsId}/characters - POST
/workspaces/{wsId}/charactersβ create character - GET
/characters/{id} - PATCH
/characters/{id}β DM-only or via review workflow - DELETE
/characters/{id}(SO)
Skills on Character
- POST
/characters/{id}/skills/{skillId}/useβ logs use, accrues XP - POST
/characters/{id}/skills/{skillId}/level-checkβ RNG check; if success: level++, +1 PP, events/notification
PP Wallet
- GET
/characters/{id}/pp - POST
/characters/{id}/pp/award(SO){ amount, reason } - POST
/characters/{id}/pp/spend{ amount, pathId, reason }
Paths on Character
- GET
/characters/{id}/paths - POST
/characters/{id}/paths/unlock(SO){ pathId } - POST
/characters/{id}/paths/invest{ pathId, points }
Catalogs (Admin/Homebrew)
- GET
/workspaces/{wsId}/catalog/skills - POST
/workspaces/{wsId}/catalog/skills(SO) β create/update - GET
/workspaces/{wsId}/catalog/paths - POST
/workspaces/{wsId}/catalog/paths(SO) β create/update
Notifications
- GET
/workspaces/{wsId}/notifications/templates - POST
/workspaces/{wsId}/notifications/templates - POST
/workspaces/{wsId}/notifications/compose{ templateId?, body?, variables, audience } - GET
/workspaces/{wsId}/notifications/logs
Rules
- GET
/workspaces/{wsId}/notification-rules - POST
/workspaces/{wsId}/notification-rulesβ create/update (basic triggers)
Review Workflow
- POST
/characters/{id}/proposals(Player){ proposedData, comment } - GET
/workspaces/{wsId}/proposals - POST
/proposals/{proposalId}/approve(SO/DM) - POST
/proposals/{proposalId}/reject(SO/DM){ reason }
Dice & Roller
- POST
/roller/flux{ poolMods, effects, bonusToRoll, bonusToCheck, tierInputs }β{ rolls, successes, tiers, notes } - GET
/workspaces/{wsId}/roller/history?characterId=...
Export/Import
- GET
/workspaces/{wsId}/exportβ application/json - POST
/workspaces/{wsId}/import?dryRun=true(SO) β report;dryRun=falseapplies
Events & Audit
- GET
/workspaces/{wsId}/events?type=...&characterId=...
WebSockets
- Connect:
wss://host/ws?v=1&workspaceId={id} - Rooms: server auto-joins client to
workspace-{id} - Event payload shape:
{ type, workspaceId, characterId?, payload, ts, seq } - Types (subset Phase 1):
character.created,stats.updated,skill.used,skill.levelUp,pp.awarded,pp.spent,path.unlocked,path.progressed,roller.result,visibility.changed,proposal.submitted,proposal.approved,proposal.rejected,notification.sent.
Example Payloads
{
"type": "skill.levelUp",
"workspaceId": "WS-123",
"characterId": "CH-123",
"payload": { "skillId": "woodworking", "from": 3, "to": 4, "ppDelta": 1 },
"ts": "2025-08-10T04:46:00Z",
"seq": 128
}
{
"name": "Level Up",
"variables": ["character.name", "skill.name", "skill.level", "pp.total"],
"audience": ["player"],
"category": "success"
}