API Design
Base URL
https://api.rgls.uk/api/v1Local development: http://localhost:3000/api/v1
The GET /health liveness probe is outside the /api/v1 prefix: GET /health → {"status":"ok"}.
Authentication
All endpoints require Authorization: Bearer <jwt> unless marked @Public().
http
GET /api/v1/me
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...Request / Response Format
- Content-Type:
application/json - Validation: Zod schemas in
packages/domain/src/schemas/, applied viaZodValidationPipe - Error format:json
{ "statusCode": 422, "error": "Unprocessable Entity", "message": ["body must not be empty"] }
Pagination
List endpoints use cursor-based pagination:
GET /api/v1/posts?limit=20&cursor=<post_id>Response:
json
{
"items": [...],
"nextCursor": "uuid-of-last-item",
"hasMore": true
}Rate Limiting
Global: 60 req/min per IP (ThrottlerGuard).
Per-route overrides:
| Endpoint | Limit |
|---|---|
POST /auth/login | 5/min |
POST /auth/register | 3/min |
POST /auth/reserve-invite | 10/min |
POST /ai/reflect | 20/min |
POST /ai/enhance-post | 10/min |
Key Endpoint Groups
Auth
| Method | Path | Description |
|---|---|---|
| POST | /auth/reserve-invite | Reserve invite code (TTL 30 min) |
| POST | /auth/register | Register with reserved code |
| POST | /auth/login | Get JWT |
| POST | /auth/logout | Invalidate session |
| POST | /auth/forgot-password | Send reset email |
| POST | /auth/reset-password | Apply new password |
Users & Identity
| Method | Path | Description |
|---|---|---|
| GET | /me | Current user profile |
| PATCH | /me | Update profile |
| DELETE | /me | GDPR self-deletion |
| GET | /users/:usernameOrId | Public profile |
| GET | /me/personas | List personas |
| POST | /me/personas | Create persona |
| PATCH | /me/personas/:id | Update persona |
| DELETE | /me/personas/:id | Delete persona |
Interests
| Method | Path | Description |
|---|---|---|
| GET | /interests/catalog | Full tree (L1→L2→L3) |
| GET | /me/interests | My selections |
| POST | /me/interests | Add / update interest |
| DELETE | /me/interests/:id | Remove interest |
Posts
| Method | Path | Description |
|---|---|---|
| GET | /feed | Home feed (For You / Following / Trending / Circles) |
| GET | /feed?journalism=true | Journalism-tagged feed |
| POST | /posts | Create post |
| GET | /posts/:id | Post detail |
| PATCH | /posts/:id | Edit post |
| DELETE | /posts/:id | Soft delete |
| POST | /posts/:id/replies | Add reply |
| POST | /posts/:id/react | React (heart/spark) |
| POST | /posts/:id/bookmark | Bookmark |
| POST | /posts/:id/repost | Repost |
| POST | /posts/:id/co-authors | Invite co-author |
| POST | /posts/:id/boost | Boost post (mana cost) |
Reputation
| Method | Path | Description |
|---|---|---|
| GET | /reputation/:userId | Per-interest reputation |
| POST | /reputation/vote | Cast peer vote |
| GET | /reputation/appeals | My appeals |
| POST | /reputation/appeals | Create appeal |
Economy
| Method | Path | Description |
|---|---|---|
| GET | /economy/wallet | My wallet |
| POST | /economy/pay | Send EmojiPay |
| GET | /economy/payments | Payment history |
Discovery
| Method | Path | Description |
|---|---|---|
| GET | /discovery/candidates | Discovery by intent |
| GET | /discovery/mentors | Mentor matching |
| PUT | /discovery/intent | Set/update connection intent |
Social
| Method | Path | Description |
|---|---|---|
| GET | /circles | My circles |
| POST | /circles | Create circle |
| POST | /circles/:id/invite | Invite user |
| POST | /circles/invitations/:id/respond | Accept/decline |
| POST | /users/:id/follow | Follow user |
| DELETE | /users/:id/follow | Unfollow |
AI
| Method | Path | Description |
|---|---|---|
| POST | /ai/reflect/start | Start reflection session |
| POST | /ai/reflect/:sessionId/answer | Answer question N |
| POST | /ai/map-interests | Map free-text to catalog |
| POST | /ai/apply-suggestions | Accept AI interest suggestions |
| POST | /ai/enhance-post | Enhance post content in composer |
Access
| Method | Path | Description |
|---|---|---|
| GET | /access/me | Current capabilities |
Wiki
| Method | Path | Description |
|---|---|---|
| GET | /wiki/:interestSlug | Current wiki entry |
| POST | /wiki/:interestSlug/proposals | Create proposal |
| POST | /wiki/proposals/:id/vote | Vote on proposal |
Notifications
| Method | Path | Description |
|---|---|---|
| GET | /notifications | Inbox |
| POST | /notifications/read | Mark as read |
| GET | /notifications/preferences | Preferences |
| PATCH | /notifications/preferences | Update preferences |
Admin (role = admin or moderator)
All admin endpoints are under /admin/ and require AdminGuard or ModeratorGuard.