am-crm

Public API Documentation (MVP Draft)

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.

Conventions

Resource Models (As Returned)

User

{
  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[]
}

UserTrait

{
  id: string,
  createdAt: string,
  userId: string,
  trait: string          // e.g. 'mentor', 'acarya', 'unit_secretary'
}

Unit

{
  id: string,
  name: string,
  description: string | null,
  unofficialRegisteredAt: string | null, // ISO
  officialRegisteredAt: string | null,   // ISO
  userIds: string[]
}

Endpoints

Health

Method Path Description Status Codes
GET / Liveness root 200
GET /health Health check (no DB) 200

Users (legacy basic CRUD; profile-oriented updates via /me)

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)

Traits (User Role/Trait Assignment)

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

Examples

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"}'

Units

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.

Profile (/me)

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 }
  ]
}

CORS Behavior

Allowed origins are enumerated via environment variables:

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.

Error Responses

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)

Roadmap (Planned / Not Implemented Yet)

These are not yet implemented but referenced in user stories & data model:

Versioning Strategy (Proposed)

Currently unversioned. Before broad adoption introduce prefix (e.g., /v1). For internal Next.js + bot consumption, unversioned iteration acceptable until contract stabilizes.

Security & Hardening TODOs

Changelog


Last updated: 2025-09-05