Allign API v2

Internal Developer Reference — Complete Endpoint Documentation

Base URL: /api/v2
Version: 2.0.0
Environment: Staging
Auth: Bearer JWT
📚

API Overview

The Allign API v2 is a RESTful JSON API that powers the Allign telemedicine platform. All endpoints live under /api/v2. Authentication uses JWT Bearer tokens. Amounts are always in paise (1 INR = 100 paise). Dates follow ISO 8601.

112
Total Endpoints
20
Router Groups
31,200
Medicines
1,935
Lab Tests
Legend for sample requests below:
REQUIRED — Field must be present in the request. Omitting it causes a 422 error.
optional — Field can be omitted. Server uses the default value (or null) when absent.
🔨

Making Requests

Every request must include Content-Type: application/json for POST/PATCH/PUT bodies. Authenticated endpoints require the Authorization header.

Authenticated Request Pattern

curl example
curl -X POST https://your-domain.com/api/v2/connect/sessions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -d '{
    "target_doctor_id": "d3af4135-fd62-4148-a316-eb94b841f693",
    "category": "General Medicine"
  }'

Understanding Request Samples

request body
{
  "phone": "+918090839108",    // REQUIRED - must provide
  "platform": "android"         // optional  - can omit
}

Understanding Response Samples

response 200
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "ONGOING",
  "created_at": "2026-02-07T14:30:00Z",   // ISO 8601 always in UTC
  "amount": 15000,                         // = 150.00 INR (paise)
  "optional_field": null                   // null when not set
}
🔒

Authentication Guide

Three roles exist: Patient (client), Doctor, and Admin. Each authenticates differently.

Patient Login (OTP Flow)

step 1
curl -X POST /api/v2/auth/request-otp \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+918090839108" }'
// Response 202: { "message": "OTP sent if phone is valid" }
step 2
curl -X POST /api/v2/auth/verify-otp \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+918090839108", "code": "743424" }'
// Response 200: { "access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer" }
step 3 — use token
curl /api/v2/users/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
// Response 200: User profile JSON

Doctor Login

curl
curl -X POST /api/v2/auth/doctor/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "doctor@allign.in", "password": "secret" }'
// Response 200: { "access_token": "...", "refresh_token": "...", "token_type": "bearer" }

Token Refresh (auto-call when access token expires with 401)

curl
curl -X POST /api/v2/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{ "refresh_token": "eyJhbG..." }'
// Old refresh token is revoked. Returns new pair.

HTTP Status Codes

CodeMeaningWhen It Happens
200OKSuccessful read, update, or idempotent action
201CreatedResource successfully created (session, review, order)
202AcceptedRequest accepted for processing (OTP send)
204No ContentSuccessful delete, no response body
400Bad RequestInvalid input, business rule violation
401UnauthorizedMissing, expired, or invalid JWT token
403ForbiddenValid token but wrong role or not allowed
404Not FoundResource does not exist
409ConflictDuplicate resource (idempotency) or state conflict
422Validation ErrorMissing required field, wrong type, constraint violation
429Too Many RequestsRate limit (OTP). Check Retry-After header
500Server ErrorUnexpected backend failure
503Service UnavailableExternal service down (SMS, payment)
🔐

Auth

Patient OTP login, doctor email/password login, token refresh, and logout.

POST/api/v2/auth/request-otpSend OTP to phone number
Public

Request Body

FieldTypeR / ODescription
phonestringREQUIREDE.164 format, e.g. +918090839108
platformstring | nulloptional"android" or "ios". Controls SMS sender ID.
sample request
{
  "phone": "+918090839108",   // REQUIRED
  "platform": "android"        // optional
}
response 202
{ "message": "OTP sent if phone is valid" }

Status Codes

202 OTP sent
422 Invalid phone format
429 Rate limited (check Retry-After header)
503 SMS service unavailable
POST/api/v2/auth/verify-otpVerify OTP, get token pair
Public

Request Body

FieldTypeR / ODescription
phonestringREQUIREDSame phone from request-otp
codestringREQUIRED6-digit OTP received via SMS
namestring | nulloptionalSets user display name on first login
sample request
{
  "phone": "+918090839108",  // REQUIRED
  "code": "743424",           // REQUIRED
  "name": "Rahul Sharma"      // optional – set on first login
}
response 200
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Status Codes

200 Verified, tokens returned
400 Invalid or expired OTP code
POST/api/v2/auth/doctor/loginDoctor email/password login
Public
sample request
{
  "email": "dr.smith@allign.in",  // REQUIRED
  "password": "s3cur3P@ss"          // REQUIRED
}
response 200
{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer"
}

Status Codes

200 Authenticated
401 Invalid credentials
POST/api/v2/auth/refreshRefresh token pair (rotation)
Public
sample request
{
  "refresh_token": "eyJhbGciOiJIUzI1NiIs..."  // REQUIRED
}
response 200
{
  "access_token": "new_eyJ...",    // New access token
  "refresh_token": "new_eyJ...",   // New refresh token (old one revoked)
  "token_type": "bearer"
}
Token Rotation: The old refresh token is automatically revoked. Always store the new pair. If you send an already-revoked token, you get 401.
POST/api/v2/auth/logoutRevoke current access token
Bearer Token
sample request
curl -X POST /api/v2/auth/logout \
  -H "Authorization: Bearer eyJhbGci..."
// No request body needed
response 200
{ "message": "Logged out" }
👤

Users (Patient Profile)

Read and update the authenticated patient's profile. Role: client only.

GET/api/v2/users/meGet my profile
Patient
sample request
curl /api/v2/users/me \
  -H "Authorization: Bearer eyJ..."
response 200 — UserOut
{
  "id": "644452ac-c508-422f-8910-f0be7a5393d3",
  "full_name": "Rahul Sharma",
  "phone": "+918090839108",
  "email": null,
  "avatar_url": "https://...assets/avatars/av_01.png",
  "avatar_source": "system",          // "system" or "user"
  "member_since": "2025-08-15T10:30:00Z",
  "is_phone_verified": true,
  "profile_completed": true,          // true when sex AND age set
  "profile_completion": 0.85,          // 0.0 to 1.0
  "age": 28,
  "sex": "male",                       // male|female|other|prefer_not_to_say
  "height_cm": 175.0,
  "weight_kg": 72.5,
  "bmi": 23.7                          // auto-calculated from height+weight
}
PATCH/api/v2/users/meUpdate my profile (partial)
Patient

Request Body (all fields optional — send only what changed)

FieldTypeR / OConstraints
full_namestringoptional1–100 chars, non-empty
ageintoptional1–150
sexstringoptionalmale | female | other | prefer_not_to_say
height_cmfloatoptional50.0–300.0
weight_kgfloatoptional10.0–500.0
sample request — update age and sex
{
  "age": 28,         // optional – only send fields you want to change
  "sex": "male"      // optional
}
response 200 — UserOut
// Returns full updated UserOut (same schema as GET /users/me)
// BMI is auto-recalculated if height or weight changed
🩺

Doctors — Public Discovery

Search, list, and view doctor profiles. Auth is optional (enables favourites).

GET/api/v2/doctors/search?q={query}Fuzzy search by name
Public Optional Auth

Query Params

ParamTypeR / ODescription
qstringREQUIREDSearch query (1–100 chars). Uses pg_trgm fuzzy matching.
limitintoptionalMax 25, default 10
offsetintoptionalDefault 0
sample request
curl "/api/v2/doctors/search?q=ankit&limit=5"
response 200 — list[DoctorOut]
[
  {
    "id": "d3af4135-...",
    "full_name": "Dr. Ankit Shah",
    "slug": "dr-ankit-shah-urology",
    "speciality_category": "Urology",
    "rating": 4.8,
    "years_experience": 12,
    "rate_per_minute": 500,          // paise (= 5.00 INR/min)
    "presence_status": "ONLINE",
    "is_favourite": false            // only if auth token sent
  }
]
GET/api/v2/doctors/List active doctors
Public

Query Params

ParamTypeR / ODescription
skipintoptionalDefault 0
limitintoptionalDefault 50
favourites_firstbooloptionalRequires auth. Default false
favourites_onlybooloptionalRequires auth. Default false
sample request
curl "/api/v2/doctors/?limit=20&favourites_first=true" \
  -H "Authorization: Bearer eyJ..."
GET/api/v2/doctors/all_doctors_listFiltered doctor listing
Public

Query Params

ParamTypeR / ODescription
statusstringoptionalONLINE, BUSY, OFFLINE
categorystringoptionalSpeciality category filter
available_forstringoptionalchat or call
featured_onlybooloptionalFeatured doctors only
sort_bystringoptionalrate | rating | experience
sort_orderstringoptionalasc or desc (default: asc)
sample request
curl "/api/v2/doctors/all_doctors_list?status=ONLINE&category=Urology&sort_by=rating&sort_order=desc"
GET/api/v2/doctors/slug/{slug}Doctor profile by slug
Public
sample request
curl "/api/v2/doctors/slug/dr-ankit-shah-urology"
response 200 — DoctorDetailOut
{
  "id": "d3af4135-...",
  "full_name": "Dr. Ankit Shah",
  "slug": "dr-ankit-shah-urology",
  "speciality_category": "Urology",
  "degrees": ["MBBS", "MS"],
  "years_experience": 12,
  "about_short": "Specialist in...",
  "rating": 4.8,
  "total_reviews": 42,
  "total_sessions": 197,
  "is_favourite": false,       // only populated if auth token sent
  "presence_status": "ONLINE"
}
GET/api/v2/doctors/{doctor_id}Doctor profile by UUID
Public
sample request
curl "/api/v2/doctors/d3af4135-fd62-4148-a316-eb94b841f693"

Returns same DoctorDetailOut as the slug endpoint.

GET/api/v2/doctors/{doctor_id}/reviewsPublic reviews (paginated)
Public
sample request
curl "/api/v2/doctors/d3af4135-.../reviews?limit=10&offset=0"
response 200 — PaginatedResponse[ReviewListItem]
{
  "items": [
    {
      "id": "a6c020eb-...",
      "rating": 5.0,
      "comment": "Excellent doctor, very helpful!",
      "patient_name_masked": "User****3d3",
      "created_at": "2026-02-07T21:56:25Z"
    }
  ],
  "total": 42, "limit": 10, "offset": 0, "has_more": true
}
📊

Doctors — Dashboard

Doctor-side dashboard. Requires doctor token.

GET/api/v2/doctors/me/overviewDashboard overview metrics
Doctor

Query Params

ParamTypeR / ODescription
timezonestringoptionalIANA tz (default UTC), e.g. Asia/Kolkata
sample request
curl "/api/v2/doctors/me/overview?timezone=Asia/Kolkata" \
  -H "Authorization: Bearer eyJ..."
response 200 — DoctorOverviewResponse
{
  "doctor": { "id": "...", "name": "Dr. Ankit", ... },
  "availability": { "is_online": true, "chat_enabled": true, "call_enabled": true },
  "metrics": {
    "todays_sessions": 6,
    "ongoing": 0,
    "pending": 10,
    "missed": 2
  }
}
GET/api/v2/doctors/me/sessionsAll sessions (filterable)
Doctor

Query Params

ParamTypeR / ODescription
statusstringoptionalREQUESTED | ONGOING | ENDED | all
from_datedateoptionalYYYY-MM-DD start
to_datedateoptionalYYYY-MM-DD end
has_followupbooloptionalFilter by followup existence
skipintoptionalDefault 0
limitintoptional1–100, default 50
sample request
curl "/api/v2/doctors/me/sessions?status=ENDED&has_followup=true&limit=20" \
  -H "Authorization: Bearer eyJ..."
GET/api/v2/doctors/me/sessions/recentLast 10 sessions
Doctor
sample request
curl "/api/v2/doctors/me/sessions/recent?limit=10&timezone=Asia/Kolkata" \
  -H "Authorization: Bearer eyJ..."
response 200 (each item)
{
  "session_id": "1d0fae55-...",
  "patient": {
    "id": "644452ac-...",
    "name": "Test Patient",
    "gender": "male",
    "age": 28,
    "avatar_url": "https://api.dicebear.com/9.x/avataaars/svg?seed=..."
  },
  "status": "ENDED",
  "duration_display": "37m 7s",
  // ... other fields ...
}
PATCH/api/v2/doctors/me/availabilitySingle toggle: online or offline
Doctor
sample request
{
  "online": true   // true = online, false = offline
}
PATCH/api/v2/doctors/me/presence_statusSet online or offline (BUSY is automatic when in session)
Doctor
sample request
{
  "presence_status": "online"  // REQUIRED – "online" | "offline" (BUSY is automatic)
}
GET/api/v2/doctors/favouritesPatient's favourite doctors
Patient
sample request
curl "/api/v2/doctors/favourites?skip=0&limit=50" \
  -H "Authorization: Bearer eyJ..."
POST/api/v2/doctors/{doctor_id}/favouriteToggle favourite
Patient
sample request
{
  "action": "add"    // REQUIRED – "add" or "remove"
}
POST/api/v2/doctors/me/sessions/{session_id}/notify-patientSend push notification
Doctor
MVP Note: Currently a no-op that returns a NotificationResult shape. Push notifications will be integrated in a future release.

Doctors — Review Management

Doctor-side review dashboard with reply CRUD. Role: doctor.

GET/api/v2/doctors/me/reviewsMy reviews (filterable)
Doctor

Query Params

ParamTypeR / ODescription
limitintoptional1–100, default 10
offsetintoptionalDefault 0
ratingintoptionalFilter by star: 1–5
has_replybooloptionalFilter by reply presence
date_fromstringoptionalISO 8601 start
date_tostringoptionalISO 8601 end
sort_bystringoptionaldate_desc | date_asc | rating_desc | rating_asc
sample request
curl "/api/v2/doctors/me/reviews?has_reply=false&sort_by=rating_desc&limit=10" \
  -H "Authorization: Bearer eyJ..."
POST/api/v2/doctors/me/reviews/{review_id}/replyReply to a review
Doctor
sample request
{
  "text": "Thank you for your feedback! Happy to help."  // REQUIRED – 1-1000 chars
}

Status Codes

201 Reply created
409 Reply already exists (use PUT to update)
PUT/api/v2/doctors/me/reviews/{review_id}/replyUpdate reply
Doctor
sample request
{
  "text": "Updated reply text here."  // REQUIRED – 1-1000 chars
}
DELETE/api/v2/doctors/me/reviews/{review_id}/replyDelete reply
Doctor
sample request
curl -X DELETE "/api/v2/doctors/me/reviews/a6c020eb-.../reply" \
  -H "Authorization: Bearer eyJ..."
// Response: 204 No Content (no body)
POST/api/v2/doctors/me/sessions/{session_id}/followupsSchedule follow-up
Doctor
sample request
{
  "scheduled_date": "2026-02-27",       // REQUIRED – YYYY-MM-DD
  "scheduled_time": "10:30:00",        // optional – HH:MM:SS
  "scheduled_timezone": "Asia/Kolkata"  // optional – default Asia/Kolkata
}

Status Codes

201 Follow-up created
409 Duplicate

Doctors — Settings & Profile

GET/api/v2/doctors/me/profileGet full profile
Doctor
sample request
curl "/api/v2/doctors/me/profile" -H "Authorization: Bearer eyJ..."
PATCH/api/v2/doctors/me/profileUpdate profile (partial)
Doctor
sample request — all fields optional, send only what changed
{
  "full_name": "Dr. Ankit Shah",      // optional – 2-100 chars
  "years_experience": 12,               // optional – 0-60
  "about_short": "Specialist in...",    // optional – max 600 chars
  "degrees": ["MBBS", "MS"],           // optional – min 1 if provided
  "speciality_category": "Urology",    // optional – from allowed list
  "languages": ["English", "Hindi"],  // optional – from allowed list
  "registration_number": "MCI12345"   // optional – min 6 chars
}
POST/api/v2/doctors/me/avatarUpload avatar (multipart)
Doctor
sample request
curl -X POST /api/v2/doctors/me/avatar \
  -H "Authorization: Bearer eyJ..." \
  -F "file=@/path/to/avatar.jpg"
// Supported: JPEG, PNG, WebP. Max 2MB.
DELETE/api/v2/doctors/me/avatarRemove avatar
Doctor
sample request
curl -X DELETE /api/v2/doctors/me/avatar -H "Authorization: Bearer eyJ..."
POST/api/v2/doctors/Create doctor (admin)
Admin

Body: DoctorCreate. Requires admin token.

PUT/api/v2/doctors/{doctor_id}Update doctor (admin/self)
Admin Doctor (self)

Body: DoctorUpdate.

🔁

Connect Now v2 — Sessions

Real-time consultation lifecycle. Uses LiveKit for media/data transport.

POST/api/v2/connect/sessionsPatient creates session
Patient

Request Body

FieldTypeR / ODescription
target_doctor_idUUIDREQUIREDDoctor to route request to
categorystringoptionalHealth category (e.g. "Urology")
symptomslist[string]optionalPatient symptoms. Default: []
active_treatmentstringoptionalCurrent treatment info
medical_historystringoptionalRelevant medical history
rate_per_minuteintoptionalRate in paise/min
sample request
{
  "target_doctor_id": "d3af4135-fd62-4148-a316-eb94b841f693",  // REQUIRED
  "category": "Urology",                                      // optional
  "symptoms": ["back pain", "frequent urination"],             // optional
  "medical_history": "Previous kidney stone 2024",             // optional
  "rate_per_minute": 500                                       // optional
}
response 201
{
  "session_id": "1d0fae55-fb8f-4085-b34c-b598e381b135",
  "status": "REQUESTED",
  "room_name": "cn-1d0fae55-fb8f-4085-b34c-b598e381b135",
  "expires_at": "2026-02-07T22:30:00Z",
  "livekit": {
    "token": "eyJ...",          // Use this to join LiveKit room
    "ws_url": "wss://lk.allign.in",
    "identity": "patient-644452ac...",
    "expires_in": 3600         // seconds until token expires
  },
  "created_at": "2026-02-07T21:56:24Z"
}
GET/api/v2/connect/sessions/requestsDoctor's pending requests
Doctor
sample request
curl "/api/v2/connect/sessions/requests" -H "Authorization: Bearer eyJ..."
response 200
{
  "items": [{
    "session_id": "1d0fae55-...",
    "status": "REQUESTED",
    "requested_at": "2026-02-07T21:56:24Z",
    "expires_at": "2026-02-07T22:30:00Z",
    "category": "Urology",
    "symptoms": ["back pain"],
    "patient": {
      "user_id": "644452ac-...",
      "name": "Rahul",
      "age": 28,
      "sex": "male",
      "initials": "RA",
      "avatar_url": "https://api.dicebear.com/9.x/avataaars/svg?seed=0e542140...&style=circle&top=shortCurly,..."
    }
  }],
  "total": 1
}
GET/api/v2/connect/sessions/requests/streamStream session requests (SSE) — real-time for Athena
Doctor

Server-Sent Events stream. Athena opens this connection to receive new session requests instantly without polling.

sample request
curl -N "/api/v2/connect/sessions/requests/stream" -H "Authorization: Bearer eyJ..."
events (text/event-stream)
event: connected
data: {"doctor_id": "d3af4135-..."}

event: session_requested
data: {"session_id": "1d0fae55-...", "status": "REQUESTED", "patient": {...}}
GET/api/v2/connect/sessions/{session_id}Get session detail
Participant
sample request
curl "/api/v2/connect/sessions/1d0fae55-..." -H "Authorization: Bearer eyJ..."
response 200
{
  "id": "1d0fae55-...",
  "patient_id": "644452ac-...",
  "doctor_id": "d3af4135-...",
  "status": "ENDED",
  "room_name": "cn-1d0fae55-...",
  "category": "Urology",
  "started_at": "2026-02-11T19:15:43Z",
  "ended_at": "2026-02-11T19:52:50Z",
  "patient": {                                // enriched patient preview
    "user_id": "644452ac-...",
    "name": "Test Patient",
    "age": 28,
    "sex": "male",
    "initials": "TP",
    "avatar_url": "https://api.dicebear.com/9.x/avataaars/svg?seed=..."
  }
}
Patient preview: The patient object is always included with avatar_url (DiceBear gender-based avatar). Available on all session statuses (REQUESTED, ONGOING, ENDED, EXPIRED, REJECTED).
POST/api/v2/connect/sessions/{session_id}/acceptDoctor accepts
Doctor
sample request
curl -X POST "/api/v2/connect/sessions/1d0fae55-.../accept" \
  -H "Authorization: Bearer eyJ..."
// No request body needed
response 200
{
  "session_id": "1d0fae55-...",
  "status": "ONGOING",
  "doctor_id": "d3af4135-...",
  "started_at": "2026-02-07T21:56:24Z",
  "livekit": { "token": "eyJ...", "ws_url": "wss://...", "identity": "doctor-...", "expires_in": 3600 }
}
Idempotent: If already ONGOING by the same doctor, returns 200 with current state.
POST/api/v2/connect/sessions/{session_id}/rejectDoctor rejects
Doctor
sample
curl -X POST "/api/v2/connect/sessions/1d0fae55-.../reject" -H "Authorization: Bearer eyJ..."
// No body. REQUESTED → REJECTED
POST/api/v2/connect/sessions/{session_id}/endEnd session
Participant
sample request
{
  "reason": "completed",   // optional – max 50 chars
  "note": null               // optional
}
Idempotent: If already ENDED, returns 200 with current state.
GET/api/v2/connect/sessions/{session_id}/tokenRefresh LiveKit token
Participant
sample
curl "/api/v2/connect/sessions/1d0fae55-.../token" -H "Authorization: Bearer eyJ..."
Access rules: Patient: REQUESTED or ONGOING. Doctor: ONGOING only (and must be the assigned doctor). Returns 409 if session is ENDED.
💬

Connect Now v2 — Messages

Message persistence and delivery/read receipts.

POST/api/v2/connect/sessions/{session_id}/messagesSend a message
Participant
sample request
{
  "client_message_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",  // REQUIRED – UUID for idempotency
  "content_type": "text",                                       // REQUIRED – text|image|file|audio
  "content": "Hello doctor, I have a question."                  // REQUIRED
}

Status Codes

201 Message created
200 Duplicate (idempotent, returns existing)
400 Session not ONGOING
GET/api/v2/connect/sessions/{session_id}/messagesList message history
Participant

Query Params

ParamTypeR / ODescription
limitintoptionalDefault 50
beforedatetimeoptionalCursor: messages before this timestamp
afterdatetimeoptionalCursor: messages after this timestamp
sample
curl "/api/v2/connect/sessions/1d0fae55-.../messages?limit=20" -H "Authorization: Bearer eyJ..."
POST/api/v2/connect/sessions/{session_id}/messages/deliveredBulk mark delivered
Recipient Only
sample request
{
  "message_ids": [          // REQUIRED – list of message UUIDs
    "msg-uuid-1",
    "msg-uuid-2",
    "msg-uuid-3"
  ]
}
response 200
{ "updated": 3 }
Important: Only the recipient (not the sender) can mark messages delivered/seen. Idempotent — re-calling returns updated: 0.
POST/api/v2/connect/sessions/{session_id}/messages/seenBulk mark seen
Recipient Only
sample request
{
  "message_ids": ["msg-uuid-1", "msg-uuid-2"]  // REQUIRED
}
// Messages must already have delivered_at set. Idempotent.
📎

Connect Now v2 — Attachments

POST/api/v2/connect/sessions/{session_id}/attachments/initGet signed upload URL
Participant
sample request
{
  "filename": "xray_report.pdf",           // REQUIRED
  "content_type": "application/pdf",         // REQUIRED – MIME type
  "size_bytes": 524288,                      // REQUIRED – file size
  "upload_mode": "SAS"                       // optional – "SAS" (recommended) or "DIRECT"
}
response 201
{
  "id": "07af53f0-...",
  "upload_url": "https://blob.core.windows.net/sessions/...?sv=...&sig=...",
  "upload_mode": "SAS",
  "status": "PENDING"
}
// Step 2: PUT the file to upload_url directly (client → Azure Blob)
// Step 3: Call POST .../complete to finalize
POST/api/v2/connect/sessions/{sid}/attachments/{aid}/completeFinalize upload
Participant
sample
curl -X POST "/api/v2/connect/sessions/.../attachments/07af53f0-.../complete" \
  -H "Authorization: Bearer eyJ..." -H "Content-Type: application/json" -d '{}'
// Verifies blob exists in Azure, validates size, marks UPLOADED
GET/api/v2/connect/sessions/{session_id}/attachmentsList attachments
Participant
sample
curl "/api/v2/connect/sessions/1d0fae55-.../attachments?include_download_url=true" \
  -H "Authorization: Bearer eyJ..."
🎥

Connect Now v2 — Recordings

POST/api/v2/connect/sessions/{session_id}/recordingsStart recording
Doctor
sample
curl -X POST "/api/v2/connect/sessions/1d0fae55-.../recordings" \
  -H "Authorization: Bearer eyJ..."
// No body. Session must be ONGOING. Idempotent: 201 new / 200 existing.
POST/api/v2/connect/sessions/{sid}/recordings/{rid}/stopStop recording
Doctor
sample
curl -X POST "/api/v2/connect/sessions/.../recordings/.../stop" -H "Authorization: Bearer eyJ..."
GET/api/v2/connect/sessions/{session_id}/recordingsList recordings
Participant
sample
curl "/api/v2/connect/sessions/1d0fae55-.../recordings" -H "Authorization: Bearer eyJ..."
📄

Connect Now v2 — Reports

Patient report uploads (PDF, images) via two-phase SAS flow. Max 10 MB. Patient uploads; both patient and doctor can view/download; only patient can delete.

POST/api/v2/connect/sessions/{session_id}/reports/initInit report upload
Patient
sample
curl -X POST "/api/v2/connect/sessions/9e818202-.../reports/init?\
original_filename=blood_report.pdf&mime_type=application/pdf&size_bytes=524288" \
  -H "Authorization: Bearer eyJ..."
response 201
{
  "report_id": "7a4ee7fb-...",
  "sas_url": "https://blob.core.windows.net/reports/...?sv=...&sig=...",
  "required_headers": { "x-ms-blob-type": "BlockBlob", "Content-Type": "application/pdf" },
  "container_name": "reports",
  "blob_name": "staging/sessions/.../reports/2026/02/08/0afc7cc_blood_report.pdf"
}
// Step 2: PUT file bytes to sas_url with required_headers
// Step 3: Call POST .../reports/{report_id}/complete to finalize

Validation

400 File > 10 MB
400 Invalid MIME (allowed: jpeg, png, webp, heic, heif, pdf)
403 Not the patient
409 Session not ONGOING/ENDED
POST/api/v2/connect/sessions/{sid}/reports/{report_id}/completeFinalize report upload
Patient
sample
curl -X POST "/api/v2/connect/sessions/.../reports/7a4ee7fb-.../complete" \
  -H "Authorization: Bearer eyJ..." -H "Content-Type: application/json" -d '{}'
// Verifies blob exists in Azure, validates size, marks UPLOADED
response 200
{
  "report_id": "7a4ee7fb-...",
  "status": "UPLOADED",
  "verified_size_bytes": 524288,
  "verified_mime_type": "application/pdf"
}
GET/api/v2/connect/sessions/{session_id}/reportsList reports
Participant
sample
curl "/api/v2/connect/sessions/9e818202-.../reports?include_download_url=true" \
  -H "Authorization: Bearer eyJ..."
response 200
{
  "items": [
    {
      "id": "7a4ee7fb-...",
      "original_filename": "blood_report.pdf",
      "mime_type": "application/pdf",
      "size_bytes": 524288,
      "created_at": "2026-02-08T01:12:26Z",
      "uploader_user_id": "644452ac-...",
      "download_url": "https://...?sv=...&sig=..."
    }
  ],
  "total": 1,
  "has_more": false
}
GET/api/v2/connect/sessions/{sid}/reports/{report_id}Get report download link
Participant
sample
curl "/api/v2/connect/sessions/.../reports/7a4ee7fb-..." -H "Authorization: Bearer eyJ..."
response 200
{
  "report_id": "7a4ee7fb-...",
  "original_filename": "blood_report.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 524288,
  "download_url": "https://...?sv=...&sig=...",
  "expires_in": 600,
  "created_at": "2026-02-08T01:12:26Z"
}
// download_url is a short-lived SAS URL (10 min expiry)
DELETE/api/v2/connect/sessions/{sid}/reports/{report_id}Delete report
Patient
sample
curl -X DELETE "/api/v2/connect/sessions/.../reports/7a4ee7fb-..." \
  -H "Authorization: Bearer eyJ..."
// Soft-delete. Only the patient (uploader) can delete.
// Doctor will get 403 Forbidden.
response 200
{
  "report_id": "7a4ee7fb-...",
  "status": "DELETED",
  "deleted_at": "2026-02-08T01:12:27Z"
}
📋

Connect Now v2 — Post-Session

Follow-ups, prescriptions, prescription PDF, lab tests, and reviews scoped to a connect session.

POST/api/v2/connect/sessions/{session_id}/followupSchedule follow-up
Doctor
sample request
{
  "scheduled_date": "2026-02-27",       // REQUIRED
  "scheduled_time": "10:30:00",        // optional
  "scheduled_timezone": "Asia/Kolkata"  // optional
}

Status Codes

201 Created
409 Duplicate
GET/api/v2/connect/sessions/{session_id}/followupView follow-up
Participant
sample
curl "/api/v2/connect/sessions/1d0fae55-.../followup" -H "Authorization: Bearer eyJ..."
POST/api/v2/connect/sessions/{session_id}/prescriptionCreate prescription
Doctor
sample request
{
  "medications": [                                // REQUIRED – at least 1 medication
    {
      "name": "Amoxicillin 500mg",              // REQUIRED
      "dosage": "1 tablet 3x daily",            // REQUIRED
      "duration": "7 days",                     // optional
      "instructions": "Take after meals"         // optional
    }
  ],
  "notes": "Complete the full course"           // optional
}
GET/api/v2/connect/sessions/{session_id}/prescriptionView prescription
Participant
sample
curl "/api/v2/connect/sessions/1d0fae55-.../prescription" -H "Authorization: Bearer eyJ..."
PUT/api/v2/connect/sessions/{session_id}/prescriptionUpdate prescription
Doctor

Full replacement of medications and notes. Invalidates cached PDF. Sends push to patient. Same request body as POST.

200 Updated
404 No prescription yet
GET/api/v2/connect/sessions/{session_id}/prescription/pdfDownload prescription PDF
Participant
sample
curl "/api/v2/connect/sessions/9e818202-.../prescription/pdf" \
  -H "Authorization: Bearer eyJ..."
response 200
{
  "download_url": "https://blob.core.windows.net/prescriptions/staging/sessions/.../prescriptions/db1380a9-....pdf?sv=...&sig=...",
  "expires_in": 600,
  "generated_at": "2026-02-08T01:16:50Z"
}
// PDF is generated on first request and cached in Azure Blob (prescriptions container).
// Subsequent calls return a fresh 10-min SAS download URL.
// Both patient and doctor can download. Session must be ONGOING or ENDED.
POST/api/v2/connect/sessions/{session_id}/lab-testsRecommend lab tests
Doctor
sample request
{
  "recommendations": [                // REQUIRED – at least 1 test
    { "test_name": "CBC", "priority": "routine", "instructions": "Fasting 8hrs" },
    { "test_name": "HbA1c", "priority": "routine" }
  ],
  "notes": "Get done within 1 week"      // optional
}
GET/api/v2/connect/sessions/{session_id}/lab-testsView lab tests
Participant
sample
curl "/api/v2/connect/sessions/1d0fae55-.../lab-tests" -H "Authorization: Bearer eyJ..."
PUT/api/v2/connect/sessions/{session_id}/lab-tests/{lab_test_id}Update lab test recommendation
Doctor

Full replacement. Same body as POST. Sends push to patient.

200 Updated
404 Not found
GET/api/v2/connect/sessions/{session_id}/reviewView session review
Participant
response 200
{
  "id": "a6c020eb-...",
  "connect_session_id": "1d0fae55-...",
  "session_id": null,                   // null for v2 sessions
  "doctor_id": "d3af4135-...",
  "rating": 5.0,
  "comment": "Excellent consultation!",
  "created_at": "2026-02-07T21:56:25Z"
}
🎥

Connect Now v2 — Video Permissions

Doctor-controlled patient video permission state machine. Doctor video is always on; patient needs explicit permission. State: NOT_ALLOWED → ALLOWED_BY_DOCTOR → VIDEO_ON / DECLINED_BY_PATIENT, with revoke returning to NOT_ALLOWED. All transitions publish to Redis for real-time delivery + FCM push.

GET/api/v2/connect/sessions/{session_id}/video-permissionGet permission status
Participant
response 200
{
  "session_id": "9e818202-...",
  "video_permission_state": "NOT_ALLOWED",   // NOT_ALLOWED | ALLOWED_BY_DOCTOR | VIDEO_ON | VIDEO_OFF | DECLINED_BY_PATIENT
  "patient_video_enabled": false,
  "consent_round": 0
}
POST/api/v2/connect/sessions/{session_id}/video-permission/requestDoctor requests video
Doctor

NOT_ALLOWED → ALLOWED_BY_DOCTOR. Sends video.permission push to patient.

200 Requested
409 Invalid state / not ONGOING
POST/api/v2/connect/sessions/{session_id}/video-permission/acceptPatient accepts
Patient

ALLOWED_BY_DOCTOR → VIDEO_ON. Patient video becomes enabled.

200 Accepted
409 Wrong state
POST/api/v2/connect/sessions/{session_id}/video-permission/declinePatient declines
Patient

ALLOWED_BY_DOCTOR → DECLINED_BY_PATIENT.

200 Declined
409 Wrong state
POST/api/v2/connect/sessions/{session_id}/video-permission/revokeRevoke permission
Participant

Either party revokes. ALLOWED_BY_DOCTOR / VIDEO_ON / VIDEO_OFF → NOT_ALLOWED.

200 Revoked
409 Cannot revoke
📞

Connect Now v2 — Call Sessions

Manage call sessions within a connect session’s LiveKit room. Tracks call type (audio/video) and video permission state. Idempotent — returns existing if one already exists for the room.

POST/api/v2/connect/calls/sessionsCreate/get call session
Participant

Request Body

FieldTypeR / ODescription
connect_session_idUUIDREQUIREDConnect session to create call for
call_typestringoptionalAUDIO (default) | VIDEO
response 201 (or 200 if exists)
{
  "id": "b4c55a12-...",
  "connect_session_id": "9e818202-...",
  "call_type": "AUDIO",
  "status": "CONNECTED",
  "livekit_room_name": "cn-9e818202-...",
  "video_permission_state": "NOT_ALLOWED",
  "patient_video_enabled": false
}
GET/api/v2/connect/calls/sessions/{call_session_id}Get call session
Participant

Returns call session details including video permission state.

200 OK
404 Not found
403 Not a participant
🔔

Device Tokens (Push Notifications)

Register FCM device tokens for push notifications. Both patients and doctors should call this on app launch and whenever the FCM token refreshes. Supports multiple devices per user. Call DELETE on logout.

POST/api/v2/users/me/device-tokenRegister device token
Auth Required

Request Body

FieldTypeR / ODescription
tokenstringREQUIREDFCM registration token
platformstringREQUIREDandroid | ios
app_versionstringoptionalApp version string
response 201
{
  "id": "a1b2c3d4-...",
  "user_id": "644452ac-...",
  "role": "client",
  "platform": "android",
  "is_active": true
}
Upsert: If the FCM token already exists, it is reassigned to the current user and reactivated.

29 push events delivered: session.accepted, session.rejected, session.ended, session.requested, session.expired, message.new, message.attachment, prescription.ready, labtests.recommended, followup.scheduled, followup.reminder, report.uploaded, review.submitted, review.reply, review.reminder, payment.success, payment.failed, video.permission, community.article, community.event
DELETE/api/v2/users/me/device-tokenDeactivate token (logout)
Auth Required

Request Body

FieldTypeR / ODescription
tokenstringREQUIREDFCM token to deactivate
204 Deactivated
404 Not found or already inactive

Reviews

POST/api/v2/reviewsPost a review
Patient
sample request
{
  "session_id": "1d0fae55-fb8f-4085-b34c-b598e381b135",  // REQUIRED – v1 or v2 session UUID
  "rating": 5.0,                                            // REQUIRED – 1.0 to 5.0
  "comment": "Very helpful, explained everything clearly."   // optional
}

Status Codes

201 Review created
400 Session not ended yet
403 Not the patient of this session
404 Session not found
409 Already reviewed this session
📅

Follow-ups

Full follow-up lifecycle: create, list, respond, reschedule, cancel.

POST/api/v2/followups/Doctor creates follow-up
Doctor
sample request
{
  "parent_session_id": "session-uuid-here",  // REQUIRED – v1 session ID
  "scheduled_date": "2026-03-15",            // REQUIRED
  "scheduled_time": "14:00:00",              // optional
  "scheduled_timezone": "Asia/Kolkata"        // optional – default Asia/Kolkata
}
GET/api/v2/followups/List my follow-ups
Patient Doctor

Query Params

ParamTypeR / ODescription
limitintoptional1–100, default 20
offsetintoptionalDefault 0
statusstringoptionalPENDING_PATIENT | ACCEPTED | REJECTED | CANCELLED
upcomingbooloptionalFuture follow-ups only
pastbooloptionalPast follow-ups only
sample
curl "/api/v2/followups/?status=PENDING_PATIENT&upcoming=true&limit=10" \
  -H "Authorization: Bearer eyJ..."
GET/api/v2/followups/{followup_id}Get detail
Participant
sample
curl "/api/v2/followups/a5eea92a-..." -H "Authorization: Bearer eyJ..."
POST/api/v2/followups/{id}/patient-responsePatient accept/reject/reschedule
Patient
sample request — accept
{
  "action": "accept"  // REQUIRED – "accept" | "reject" | "reschedule"
}
sample request — reschedule
{
  "action": "reschedule",          // REQUIRED
  "proposed_date": "2026-03-20",   // REQUIRED when action=reschedule
  "proposed_time": "15:00:00"     // optional
}
POST/api/v2/followups/{id}/doctor-rescheduleDoctor accept/reject reschedule
Doctor
sample request
{
  "accept": true  // REQUIRED – true to accept patient's proposed date, false to reject
}
POST/api/v2/followups/{id}/cancelCancel follow-up
Patient Doctor
sample request
{
  "reason": "Schedule conflict"  // optional – cancellation reason
}
📈

Analytics

GET/api/v2/analytics/user/overviewPatient stats
Patient
response 200
{
  "sessions_count": 108,          // completed sessions (v1+v2)
  "followups_count": 4,
  "bmi": 23.7,                      // from profile, nullable
  "doctors_consulted_count": 1    // distinct doctors (v1+v2)
}
GET/api/v2/analytics/user/sessionsSession history
Patient
sample
curl "/api/v2/analytics/user/sessions?limit=20&offset=0" -H "Authorization: Bearer eyJ..."
GET/api/v2/analytics/user/ordersOrder history
Patient
sample
curl "/api/v2/analytics/user/orders?limit=20&offset=0" -H "Authorization: Bearer eyJ..."
GET/api/v2/analytics/user/rechargesRecharge history
Patient
sample
curl "/api/v2/analytics/user/recharges?limit=20&offset=0" -H "Authorization: Bearer eyJ..."
GET/api/v2/analytics/doctor/performancePerformance dashboard
Doctor

Query Params

ParamTypeR / ODescription
timezonestringoptionalDefault UTC. e.g. Asia/Kolkata
date_rangestringoptionaltoday | week | month | year | all_time (default)
sample
curl "/api/v2/analytics/doctor/performance?date_range=month&timezone=Asia/Kolkata" \
  -H "Authorization: Bearer eyJ..."
GET/api/v2/analytics/doctor/reviews/metricsReview metrics
Doctor
sample
curl "/api/v2/analytics/doctor/reviews/metrics?date_from=2026-01-01&date_to=2026-01-31" \
  -H "Authorization: Bearer eyJ..."
GET/api/v2/analytics/doctor/reviews/rating-trendRating trend
Doctor

Query Params

ParamTypeR / ODescription
periodstringoptionalday (default) | week | month
date_fromstringoptionalISO 8601
date_tostringoptionalISO 8601
GET/api/v2/analytics/doctor/reviews/rating-distributionStar breakdown
Doctor
sample
curl "/api/v2/analytics/doctor/reviews/rating-distribution" -H "Authorization: Bearer eyJ..."
💊

Medicines (Search / Catalog)

Typeahead autocomplete for 31,200+ medicines. Uses a three-phase search strategy: prefix match → contains match → fuzzy fallback (pg_trgm). No auth required — this is public reference data. Frontend should debounce requests by 200–300ms.

GET/api/v2/medicines/search?q=amox&limit=10Typeahead search
Public

Query Parameters

ParamTypeR / ODescription
qstringREQUIREDSearch query (min 2, max 100 chars). Brand name, generic name, or salt.
limitintegeroptional1–25, default 10
curl example
curl "/api/v2/medicines/search?q=amoxyclav&limit=5"
response 200
[
  {
    "id": "a16efb82-14a5-4429-92e7-855b009b5e4d",
    "name": "Amoxyclav 625 Tablet",
    "form": "tablet",              // tablet | capsule | injection | syrup | cream | gel | drops | ...
    "provider": "1mg"
  },
  {
    "id": "48219863-5d68-4667-8221-148a3c96d840",
    "name": "Amoxyclav 375 Tablet",
    "form": "tablet",
    "provider": "1mg"
  }
]
Three-phase search:
1. Prefix — names starting with query (fastest, B-tree index)
2. Contains — names containing query anywhere, e.g. “paracetamol” finds “Genericart Paracetamol 650mg Tablet” (GIN index)
3. Fuzzy — handles typos, e.g. “amoxyclv” finds “Amoxyclav” (pg_trgm similarity)
GET/api/v2/medicines/{medicine_id}Full medicine details
Public

Path Parameters

ParamTypeR / ODescription
medicine_idUUIDREQUIREDMedicine ID from search results
response 200
{
  "id": "a16efb82-14a5-4429-92e7-855b009b5e4d",
  "name": "Amoxyclav 625 Tablet",
  "form": "tablet",
  "provider": "1mg",
  "product_introduction": "Amoxyclav 625 Tablet is used in the treatment of...",
  "uses": ["Bacterial infections", "Skin infections"],
  "how_it_works": "Amoxyclav 625 Tablet is a combination of...",
  "safety_advice": { "advice": "Alcohol\nCONSULT YOUR DOCTOR..." },
  "source_url": "https://www.1mg.com/drugs/amoxyclav-625-tablet-12345",
  "created_at": "2026-02-11T22:02:06.360732Z"
}
200 Medicine found
404 Not found
🧪

Lab Tests (Search / Catalog)

Typeahead autocomplete for 1,935+ lab tests (Dr. Lal PathLabs). Searches by test name and test code. Same three-phase strategy as medicines. No auth required.

GET/api/v2/lab-tests/catalog/search?q=thyroid&limit=10Typeahead search
Public

Query Parameters

ParamTypeR / ODescription
qstringREQUIREDSearch query (min 2, max 100 chars). Test name or test code (e.g. “CBC”).
limitintegeroptional1–25, default 10
curl examples
// Search by name
curl "/api/v2/lab-tests/catalog/search?q=thyroid&limit=5"

// Search by test code
curl "/api/v2/lab-tests/catalog/search?q=CBC&limit=5"
response 200
[
  {
    "id": "b7c8d9e0-1234-5678-abcd-ef0123456789",
    "name": "Thyroid Profile, Free",
    "code": "Z045",
    "provider": "lal_pathlabs"
  },
  {
    "id": "c8d9e0f1-2345-6789-abcd-ef0123456789",
    "name": "Thyroid, Comprehensive Panel",
    "code": "Z120",
    "provider": "lal_pathlabs"
  }
]
Code search: Typing a test code like “CBC” or “Z045” directly matches the code field via prefix match, making it fast to find tests by their lab code.
📦

Attachments (General)

General-purpose file uploads. Scopes: PROFILE, SESSION, REPORT, RECORDING.

POST/api/v2/attachments/initInitialize upload
Bearer Token
sample request
{
  "scope_type": "SESSION",                 // REQUIRED – PROFILE|SESSION|REPORT|RECORDING
  "scope_id": "session-uuid-here",        // REQUIRED for SESSION/REPORT/RECORDING
  "filename": "report.pdf",               // REQUIRED
  "content_type": "application/pdf",       // REQUIRED
  "size_bytes": 1048576,                   // REQUIRED
  "upload_mode": "SAS"                     // optional – SAS (default) or DIRECT
}
POST/api/v2/attachments/{id}/uploadDirect upload (multipart)
Bearer Token
sample
curl -X POST "/api/v2/attachments/07af53f0-.../upload" \
  -H "Authorization: Bearer eyJ..." -F "file=@report.pdf"
POST/api/v2/attachments/{id}/completeComplete SAS upload
Bearer Token
POST/api/v2/attachmentsSingle-step upload
Bearer Token
sample (multipart/form-data)
curl -X POST /api/v2/attachments \
  -H "Authorization: Bearer eyJ..." \
  -F "scope_type=SESSION" \
  -F "scope_id=session-uuid" \
  -F "file=@report.pdf"
GET/api/v2/attachmentsList by scope
Bearer Token
sample
curl "/api/v2/attachments?scope_type=SESSION&scope_id=uuid&include_download_url=true" \
  -H "Authorization: Bearer eyJ..."
GET/api/v2/attachments/{id}Get + download URL
Bearer Token
DELETE/api/v2/attachments/{id}Soft delete
Bearer Token
sample
curl -X DELETE "/api/v2/attachments/07af53f0-..." -H "Authorization: Bearer eyJ..."
// Response: 204 No Content
📌

Categories

GET/api/v2/categories/healthHealth categories (by sex)
Patient
sample
curl "/api/v2/categories/health" -H "Authorization: Bearer eyJ..."
Prerequisite: Requires profile_completed=true (sex + age set). Returns 409 PROFILE_INCOMPLETE if not set.
🌐

Community

GET/api/v2/community/articlesList articles
Public
sample
curl "/api/v2/community/articles?limit=20&category=wellness&sort_by=published_at&sort_order=desc"
GET/api/v2/community/eventsList events
Public
sample
curl "/api/v2/community/events?event_type=online&status=upcoming&sort_by=event_date"
💳

Payments (Cashfree)

POST/api/v2/payments/cashfree/ordersCreate payment order
Patient
sample request
{
  "amount": 50000,      // REQUIRED – amount in paise (= 500.00 INR)
  "offer_id": "uuid"   // optional – wallet offer to apply
}
response 201
{
  "order_id": "cf_order_abc123",
  "payment_session_id": "session_xyz...",  // Use in Cashfree SDK
  "amount": 50000,
  "status": "PENDING"
}
GET/api/v2/payments/cashfree/orders/{order_id}/verifyVerify payment
Patient
sample
curl "/api/v2/payments/cashfree/orders/cf_order_abc123/verify" -H "Authorization: Bearer eyJ..."
// Idempotent: won't double-credit wallet
POST/api/v2/payments/cashfree/webhookCashfree webhook
Server-to-Server
Internal: Called by Cashfree servers. Signature-verified. No client integration needed.
💰

Wallet

GET/api/v2/wallet/offersActive recharge offers
Public
sample
curl "/api/v2/wallet/offers"
// Returns list of WalletOfferOut. Cached 5 min (public).
🛡

Admin — Authentication

POST/api/v2/admin/auth/loginAdmin login
Public
sample request
{
  "username": "admin",       // REQUIRED – username or email
  "password": "s3cur3P@ss"   // REQUIRED
}
GET/api/v2/admin/auth/meCurrent admin profile
Admin
sample
curl "/api/v2/admin/auth/me" -H "Authorization: Bearer eyJ..."
👥

Admin — User Management

All endpoints require Admin token.

GET/api/v2/admin/usersList users
sample
curl "/api/v2/admin/users?limit=20&offset=0" -H "Authorization: Bearer eyJ..."
GET/api/v2/admin/users/{user_id}Get user
sample
curl "/api/v2/admin/users/644452ac-..." -H "Authorization: Bearer eyJ..."
PATCH/api/v2/admin/users/{user_id}Update user
sample request
{
  "full_name": "Updated Name",  // optional
  "age": 30                       // optional
}
PATCH/api/v2/admin/users/{user_id}/statusActivate/deactivate
sample request
{
  "is_active": false  // REQUIRED
}
GET/api/v2/admin/users/{uid}/analytics/overviewUser analytics
sample
curl "/api/v2/admin/users/644452ac-.../analytics/overview" -H "Authorization: Bearer eyJ..."
GET/api/v2/admin/users/{uid}/analytics/sessionsUser sessions
sample
curl "/api/v2/admin/users/644452ac-.../analytics/sessions?limit=20" -H "Authorization: Bearer eyJ..."
GET/api/v2/admin/users/{uid}/analytics/ordersUser orders
Admin
GET/api/v2/admin/users/{uid}/analytics/rechargesUser recharges
Admin
📋

Admin — Categories

CRUD for health categories. All require Admin.

POST/api/v2/admin/categoriesCreate
sample request
{
  "name": "Dermatology",     // REQUIRED
  "description": "Skin care",  // optional
  "is_active": true            // optional – default true
}
GET/api/v2/admin/categoriesList all
sample
curl "/api/v2/admin/categories?limit=50" -H "Authorization: Bearer eyJ..."
GET/api/v2/admin/categories/{id}Get one
Admin
PATCH/api/v2/admin/categories/{id}Update
sample request
{ "is_active": false }  // all fields optional
DELETE/api/v2/admin/categories/{id}Delete
sample
curl -X DELETE "/api/v2/admin/categories/uuid-here" -H "Authorization: Bearer eyJ..."
// 204 No Content
💰

Admin — Wallet Offers

POST/api/v2/admin/wallet/offersCreate offer
sample request
{
  "title": "Starter Pack",    // REQUIRED
  "amount": 500.00,            // REQUIRED – INR (converted to paise internally)
  "bonus_amount": 50.00,       // optional – bonus in INR
  "valid_from": "2026-02-01",  // REQUIRED
  "valid_until": "2026-03-01"  // REQUIRED
}
GET/api/v2/admin/wallet/offersList all
Admin
GET/api/v2/admin/wallet/offers/{id}Get one
Admin
PATCH/api/v2/admin/wallet/offers/{id}Update
Admin
DELETE/api/v2/admin/wallet/offers/{id}Delete
Admin
📰

Admin — Articles

POST/api/v2/admin/community/articlesCreate
sample request
{
  "title": "5 Tips for Better Sleep",  // REQUIRED
  "excerpt": "Sleep is essential...",    // REQUIRED
  "content": "Full article body...",     // REQUIRED
  "category": "wellness",               // optional
  "author": "Dr. Smith",                // optional
  "image_url": "https://..."             // optional
}
GET/api/v2/admin/community/articlesList (incl. drafts)
Admin
GET/api/v2/admin/community/articles/{id}Get one
Admin
PATCH/api/v2/admin/community/articles/{id}Update
Admin
DELETE/api/v2/admin/community/articles/{id}Delete (soft)
Admin
🎉

Admin — Events

POST/api/v2/admin/community/eventsCreate
sample request
{
  "title": "Health Awareness Webinar",  // REQUIRED
  "description": "Join us for...",        // REQUIRED
  "event_date": "2026-03-15T10:00:00Z",   // REQUIRED
  "event_type": "online",                 // optional – online|in_person|hybrid
  "category": "wellness",                 // optional
  "image_url": "https://..."              // optional
}
GET/api/v2/admin/community/eventsList (incl. inactive)
Admin
GET/api/v2/admin/community/events/{id}Get one
Admin
PATCH/api/v2/admin/community/events/{id}Update
Admin
DELETE/api/v2/admin/community/events/{id}Delete (soft)
Admin