Status: Updated for refactored single-unit user model, profile (/me) endpoints, lessons JSON array, unit registration dates. Future domain endpoints (contact logs, initiation, attention, auth) will extend this spec or move to tRPC.
Base URL (local dev): http://localhost:3001
All responses are JSON unless noted. Timestamps are ISO8601 strings. Currently no authentication / authorization middleware is enforced (MVP scaffolding). IMPORTANT: In production this must be restricted (session / token) prior to exposure.
id
fields are opaque UUID strings (from Prisma default).404 not found
(where implemented) else silently ignore on delete (idempotent style).201
with resource body.204
with empty body.400
with text message body.{
id: string,
email: string,
fullName: string | null,
spiritualName: string | null,
displayName: string | null,
telegramHandle: string | null,
whatsapp: string | null,
photoUrl: string | null,
dateOfBirth: string | null, // ISO date
nationality: string | null,
languages: string | null, // comma separated or null
location: string | null,
preferredLanguage: string | null,
unitId: string | null, // single unit membership
mentorId: string | null,
acaryaId: string | null,
lessons: { lesson: number, receivedAt: string | null }[], // ordered 0..6
menteeIds: string[], // users mentored by this user
initiateIds: string[], // users initiated by this user (placeholder)
traits: UserTrait[]
}
{
id: string,
createdAt: string,
userId: string,
trait: string // e.g. 'mentor', 'acarya', 'unit_secretary'
}
{
id: string,
name: string,
description: string | null,
unofficialRegisteredAt: string | null, // ISO
officialRegisteredAt: string | null, // ISO
userIds: string[]
}
Method | Path | Description | Status Codes |
---|---|---|---|
GET | / |
Liveness root | 200 |
GET | /health |
Health check (no DB) | 200 |
Method | Path | Description | Body (Request) | Responses |
---|---|---|---|---|
GET | /users |
List users (with traits) | – | 200 [User[]] |
POST | /users |
Create user | { email: string } |
201 User / 400 (missing email) |
PUT | /users/:id |
Update email only (temporary) | { email?: string } |
200 User / 404 |
DELETE | /users/:id |
Delete user | – | 204 (idempotent) |
Method | Path | Description | Body | Responses |
---|---|---|---|---|
GET | /users/:id/traits |
List traits for user | – | 200 [UserTrait[]] |
POST | /users/:id/traits |
Add trait (idempotent by trait) | { trait: string } |
201 UserTrait / 400 |
DELETE | /users/:id/traits/:trait |
Remove trait | – | 204 |
Create user:
curl -X POST http://localhost:3001/users \
-H 'Content-Type: application/json' \
-d '{"email":"alice@example.com","name":"Alice"}'
Add mentor trait:
curl -X POST http://localhost:3001/users/USER_ID/traits \
-H 'Content-Type: application/json' \
-d '{"trait":"mentor"}'
Method | Path | Description | Body | Responses |
---|---|---|---|---|
GET | /units |
List units (with userIds) | – | 200 [Unit[]] |
POST | /units |
Create unit | { name: string, description?: string } |
201 Unit / 400 |
PUT | /units/:id |
Update unit (name, description) | { name?: string, description?: string } |
200 Unit / 404 |
DELETE | /units/:id |
Delete unit | – | 204 |
Membership management is now implicit: set a user’s
unitId
via profile update instead of separate membership endpoints.
Authenticated endpoints (placeholder auth; currently header Authorization: Bearer <userId>
for dev only):
Method | Path | Description | Body (Request) | Responses |
---|---|---|---|---|
GET | /me |
Get current user profile | – | 200 User / 401 |
PUT | /me |
Update profile & lessons | Partial user fields (see below) | 200 User / 401 |
PUT | /me/mentees |
Set mentee list (mentor link) | { menteeIds: string[] } |
200 User / 401 |
POST | /me/photo |
Upload/replace profile photo | multipart/form-data field photo |
200 { url } / 401 / 400 |
Profile update accepted fields: fullName, spiritualName, displayName, telegramHandle, whatsapp, photoUrl, dateOfBirth (ISO), nationality, languages, location, preferredLanguage, unitId, mentorId, acaryaId, lessons
.
Photo upload example (replace existing photo):
curl -X POST http://localhost:3001/me/photo \
-H 'Authorization: Bearer <token>' \
-F 'photo=@/path/to/image.jpg'
Lessons array example:
{
"lessons": [
{ "lesson": 0, "receivedAt": "2025-01-10T00:00:00.000Z" },
{ "lesson": 1, "receivedAt": null }
]
}
Allowed origins are enumerated via environment variables:
LOCAL_FRONTEND_URL
VERCEL_PROD_URL
VERCEL_DEV_URL
If request Origin header matches one of the populated values it is echoed back; otherwise requests without an Origin are allowed (*
), and non-matching origins are rejected (empty origin string response). Adjust prior to production hardening.
Scenario | Status | Body |
---|---|---|
Missing required field (e.g., email) | 400 | text/plain descriptive message |
Resource not found (update) | 404 | text/plain “not found” |
Delete non-existent resource | 204 | empty (idempotent) |
These are not yet implemented but referenced in user stories & data model:
POST /contact-logs
, GET /mentees/:id/contact-logs
GET/PUT /users/:id/practice
for regularity updatesGET /attention
(derived list)POST /auth/telegram/init
, POST /auth/telegram/confirm
POST /auth/magic-link
, GET /auth/session
, POST /auth/logout
Currently unversioned. Before broad adoption introduce prefix (e.g., /v1
). For internal Next.js + bot consumption, unversioned iteration acceptable until contract stabilizes.
Last updated: 2025-09-05