HTTP

Contracts you can grow into.

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.
POST/api/auth/login

Create 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" } }
POST/api/auth/switch-role

Switch workspace

Issues a new session cookie for another role without leaving the product.

{ "role": "provider" }
{ "session": { "role": "provider" } }
GET/api/patients

List patients

Provider and admin roster. Patient role never receives this collection.

Authorization: Session cookie
{ "patients": [{ "id": "pat-1", "status": "active" }] }
POST/api/health-logs

Write a health log

Weight, 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 } }
POST/api/meals/estimate

Estimate meal from photo

Returns calories and macros. Client must confirm or correct before POST /api/meals.

{ "name": "Salmon bowl", "photoUrl": "…" }
{ "calories": 580, "proteinG": 40, "confidence": 0.86 }
PATCH/api/appointments/:id

Update visit status

scheduled → confirmed → completed | cancelled | no-show

{ "status": "confirmed" }
{ "appointment": { "id": "apt-1", "status": "confirmed" } }
POST/api/messages

Send a secure message

Threads 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 } }
PATCH/api/documents/:id

Sign or archive a consent

pending → signed. Templates live with patientId null.

{ "status": "signed" }
{ "document": { "status": "signed" } }