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=false
applies
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"
}