Files

88 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API.md
Base path: `/api`. JSON in, JSON out. Auth via session cookie.
## Response envelope
Success: `{ "ok": true, "data": { ... } }`
Failure: `{ "ok": false, "error": { "code": "INSUFFICIENT_ENERGY", "message": "Not enough energy." } }`
## Status codes
| Code | Use |
|---|---|
| 200 | success |
| 201 | created (register, create hero) |
| 400 | validation failed (`VALIDATION_ERROR`) |
| 401 | not logged in (`UNAUTHENTICATED`) |
| 403 | logged in but not allowed (`FORBIDDEN`, `BANNED`) |
| 404 | not found (`NOT_FOUND`) |
| 409 | conflict (`USERNAME_TAKEN`, `HERO_EXISTS`, `EXPEDITION_ACTIVE`) |
| 422 | rule violation (`INSUFFICIENT_ENERGY`, `INSUFFICIENT_GOLD`, `LEVEL_TOO_LOW`, `NOT_READY`) |
| 429 | rate limited |
| 500 | unexpected (never leak stack traces) |
## Endpoints
### Auth (public unless noted)
| Method | Path | Body | Returns |
|---|---|---|---|
| POST | `/auth/register` | `{username, password}` | `{user:{id,username}}` + sets session |
| POST | `/auth/login` | `{username, password}` | `{user:{id,username}, hasHero}` |
| POST | `/auth/logout` 🔒 | – | `{}` |
| GET | `/auth/me` 🔒 | – | `{user:{id,username}, hasHero}` |
Validation: username 3–20 chars `[A-Za-z0-9_]`; password 8–72 chars.
Login failure always returns the same generic message (`INVALID_CREDENTIALS`) — don't reveal whether the username exists.
### Character 🔒
| Method | Path | Body | Returns |
|---|---|---|---|
| POST | `/character` | `{name, class}` | `{character}` |
| GET | `/character` | – | `{character, derived, equipment, energy:{current,max,nextTickInSec}}` |
| POST | `/character/allocate` | `{str,agi,int,vit}` (points to add) | `{character, derived}` |
| POST | `/character/rest` | – | heals to full for gold cost (see BALANCE) |
### Hunting 🔒
| Method | Path | Body | Returns |
|---|---|---|---|
| GET | `/zones` | – | zones with `unlocked` flag |
| POST | `/hunt` | `{zoneId}` | `{result:{won,rounds[],xp,gold,loot[],leveledUp,newLevel}, character}` |
| GET | `/combat-log?limit=20` | – | recent fights |
### Inventory 🔒
| Method | Path | Body | Returns |
|---|---|---|---|
| GET | `/inventory` | – | `{items:[{inventoryId,item,quantity,equippedSlot}]}` |
| POST | `/inventory/equip` | `{inventoryId}` | `{equipment, derived}` |
| POST | `/inventory/unequip` | `{slot}` | `{equipment, derived}` |
| POST | `/inventory/use` | `{inventoryId}` | `{character, message}` |
### Shop 🔒
| Method | Path | Body | Returns |
|---|---|---|---|
| GET | `/shop` | – | stock list with prices and `canAfford`, `levelOk` |
| POST | `/shop/buy` | `{itemId, quantity}` (1–99) | `{gold, inventory}` |
| POST | `/shop/sell` | `{inventoryId, quantity}` | `{gold, inventory}` |
### Expeditions 🔒
| Method | Path | Body | Returns |
|---|---|---|---|
| GET | `/expeditions` | – | available defs + active one (with `remainingSec`) |
| POST | `/expeditions/start` | `{defId}` | `{expedition}` |
| POST | `/expeditions/claim` | – | `{rewards, character}` |
### Leaderboard & heroes (public read)
| Method | Path | Query | Returns |
|---|---|---|---|
| GET | `/leaderboard` | `type=level|gold|kills`, `page=1` | top 50 per page |
| GET | `/heroes/:name` | – | public profile (name, class, level, kills, equipped item names) |
### Misc
| GET | `/health` | – | `{ok:true}` |
## Rules for every route
1. Validate with zod; on failure → 400 `VALIDATION_ERROR` with field messages.
2. Never trust client-supplied ids for ownership: always scope by `req.session.userId` → character.
3. Responses never include `password_hash` or session data.
4. State-changing endpoints are POST. GET must never modify state.
5. Return the *updated* character where relevant so the UI can refresh without a second call.