API reference
All REST endpoints live under /api/v1. Requests carry a Keycloak
Bearer access token (realm alpun, client alpun-app, Authorization Code
- PKCE); the backend validates RS256 tokens against cached JWKS (see Backend → Authentication).
Wallet linking
Linking a Solana wallet to the account — required for staking and NFT claims, not for login. Both endpoints require a valid Keycloak bearer:
POST /api/v1/wallet/challenge
POST /api/v1/wallet/link
The challenge is a domain-bound nonce; link submits the wallet public
key and the Ed25519 signature over the challenge text.
Player
GET /api/v1/players/me
PATCH /api/v1/players/me
GET /api/v1/players/me/alpacas
GET /api/v1/players/me/inventory
GET /api/v1/players/me/staking
Game
POST /api/v1/game/sessions
GET /api/v1/game/sessions/:sessionId
POST /api/v1/game/commands
Example command:
{
"commandId": "01J2COMMAND...",
"sessionId": "01J2SESSION...",
"sequence": 48,
"type": "collect_resource",
"payload": { "resourceNodeId": "farm-wool-42" },
"clientTimestamp": "2026-07-17T11:15:00Z"
}
Response:
{
"commandId": "01J2COMMAND...",
"accepted": true,
"serverSequence": 49,
"changes": { "woolDelta": 2, "energyDelta": -1 },
"serverTimestamp": "2026-07-17T11:15:00.150Z"
}
Missions
GET /api/v1/missions
POST /api/v1/missions/:missionId/start
POST /api/v1/player-missions/:playerMissionId/complete
GET /api/v1/player-missions/active
Staking
GET /api/v1/staking/config
GET /api/v1/staking/positions
POST /api/v1/staking/transactions/deposit
POST /api/v1/staking/transactions/withdraw
POST /api/v1/staking/transactions/claim
POST /api/v1/staking/synchronize
Transaction-building endpoints return an unsigned (or partially prepared) transaction for the wallet to inspect and sign. The backend never signs as the player.
Leaderboard
GET /api/v1/seasons/current
GET /api/v1/leaderboards/:leaderboardId
GET /api/v1/leaderboards/:leaderboardId/me
WebSocket protocol
WebSockets carry: active game session updates, energy updates, mission completion, staking synchronization, live leaderboard movement, maintenance announcements. They do not carry every animation or movement frame.
Connection flow
1. Client obtains access token over HTTPS.
2. Client opens WebSocket.
3. Client sends authentication message.
4. Backend validates token and associates the connection with the player.
5. Backend sends the initial session snapshot.
6. Later messages contain state deltas.
Client message
{
"id": "01J2MESSAGE...",
"type": "game.command",
"sequence": 120,
"payload": { "command": "interact", "targetId": "wool-station-4" }
}
Server message
{
"id": "01J2SERVER...",
"type": "game.state_delta",
"sequence": 121,
"payload": { "energy": 72, "inventoryDelta": { "wool": 3 } }
}
When multiple API replicas run, cross-instance WebSocket fan-out uses Redis Pub/Sub or NATS — MongoDB is the durable store, not a message bus.