/api/auth/loginCreate session
Opens a pre-seeded role session. No password. Admin is always listed last at the client.
{ "role": "patient", "userId": "pat-1" }{ "session": { "role": "patient", "name": "Maya Chen" } }HTTP
Session cookie auth, JSON bodies, and resource URLs that match the Prisma schema. Nothing here talks to a live payer, identity provider, or EHR — the shapes are production-ready.
Authentication
POST /api/auth/login Cookie: metabology_session=<base64url session> All subsequent requests send the cookie. Role isolation is enforced in middleware by URL prefix.
/api/auth/loginOpens a pre-seeded role session. No password. Admin is always listed last at the client.
{ "role": "patient", "userId": "pat-1" }{ "session": { "role": "patient", "name": "Maya Chen" } }/api/auth/switch-roleIssues a new session cookie for another role without leaving the product.
{ "role": "provider" }{ "session": { "role": "provider" } }/api/patientsProvider and admin roster. Patient role never receives this collection.
Authorization: Session cookie
{ "patients": [{ "id": "pat-1", "status": "active" }] }/api/health-logsWeight, waist, vitals, glucose. Same shape a Bluetooth tape would POST later.
{ "patientId": "pat-1", "weightLbs": 186.2, "waistIn": 34.5 }{ "log": { "id": "hl-50001", "bmi": 30.4 } }/api/meals/estimateReturns calories and macros. Client must confirm or correct before POST /api/meals.
{ "name": "Salmon bowl", "photoUrl": "…" }{ "calories": 580, "proteinG": 40, "confidence": 0.86 }/api/appointments/:idscheduled → confirmed → completed | cancelled | no-show
{ "status": "confirmed" }{ "appointment": { "id": "apt-1", "status": "confirmed" } }/api/messagesThreads are scoped to a patient. Sender role is recorded on every line.
{ "threadId": "th-1", "patientId": "pat-1", "body": "…" }{ "message": { "id": "msg-50002", "read": false } }/api/documents/:idpending → signed. Templates live with patientId null.
{ "status": "signed" }{ "document": { "status": "signed" } }