Endpoints
Every route a server-side key can call, one page each.
Each route below has its own page: what it is for, every parameter, what comes
back, and the mistakes that produce a 400.
What every request needs
x-api-key: mk_…
x-end-user-id: <patient id> # OTP and 🔒 routes onlyThe API key is the credential — there is nothing to sign — so it belongs on your
server and nowhere else. Requests are refused unless they come from an address on
the key's IP allowlist. OTP and 🔒 routes also
need x-end-user-id, naming the patient the request is for; see OTP-gated routes.
Two things are decided for you and cannot be sent:
workspaceIdcomes from the key. Every route is scoped to the workspace the key is registered against, so aworkspaceIdin a query string or body is either ignored or overwritten.- The admin identity. The gateway calls the Medos core as your workspace's admin, which is why routes that read a patient's own records are scoped server-side rather than by anything you send.
🔒 marks a route that additionally needs an
OTP-verified phone, and the same x-end-user-id that verification was made under.
This list is the whole surface
API keys can call these routes and no others. The gateway has routes of its own
for the widget that are not on this list; an API key gets a 403 on those, and
an unknown path is a 404. Nothing is forwarded on to the Medos core. If you
need something that is missing, ask us to open it rather than probing for it.
Appointments
| Method | Path | What it does |
|---|---|---|
GET | /v1/appointments/available-slots | Bookable slots for a doctor on a date |
GET | /v1/appointments/doctors/:doctorId/available-slots | Same grid, doctor in the path |
POST | /v1/appointments/book-appointment 🔒 | Book a scheduled slot |
POST | /v1/appointments/book-appointment-unified 🔒 | Book, buy a pack, or spend one |
POST | /v1/appointments/reserve-slot 🔒 | Hold a slot unpaid, optionally with checkout |
POST | /v1/appointments/confirm-payments | Settle an online payment on return |
POST | /v1/appointments/:appointmentId/reschedule | Move to a new slot |
PATCH | /v1/appointments/:appointmentId/status | Change the appointment's status |
POST | /v1/appointments/:appointmentId/cancel | Cancel, with optional refund |
Booking without OTP
There is no separate set of paths for this. The 🔒 booking routes above skip the one-time code when you call them with an API key instead of a widget session — see Booking without OTP.
QMS (queue)
| Method | Path | What it does |
|---|---|---|
GET | /v1/qms-appointments/doctor/shifts | A doctor's queue shifts for a date |
POST | /v1/qms-appointments/pre/book 🔒 | Reserve a token for a future shift |
POST | /v1/qms-appointments/immediate/book 🔒 | Take a token in the running queue |
Session packs
| Method | Path | What it does |
|---|---|---|
GET | /v1/session/packs | The clinic's pack catalog |
POST | /v1/session/packs 🔒 | Buy a pack standalone → checkout |
POST | /v1/session/packs/confirm | Settle a pack payment |
Patients
| Method | Path | What it does |
|---|---|---|
POST | /v1/patients/send-phone-verification-otp | Send a verification code |
POST | /v1/patients/verify-phone-verification-otp | Verify, open the gate, return the patient's records |
GET | /v2/patients/search-by-phone 🔒 | Patients, active packs and catalog for a phone |
PUT | /v1/patients/:patientId/basic-details | Edit name, contact, address, form values |
Workspace
| Method | Path | What it does |
|---|---|---|
GET | /v2/workspaces | The whole clinic: addresses, doctors, profiles, pricing |
GET | /v2/workspaces/patient-form | The patient-form schema |
PATCH | /v2/workspaces/patient-form | Replace the schema |
Public profiles
| Method | Path | What it does |
|---|---|---|
GET | /v1/public-profiles/:profileId | The one enriched read — slug, gallery, faqs, seo |
POST | /v1/public-profiles/add-update | Create or update a profile, with an optional image |
DELETE | /v1/public-profiles/:profileId | Delete a profile |
Staff
| Method | Path | What it does |
|---|---|---|
POST | /v1/users | Add a staff user to the workspace |
GET | /v1/users | List staff at an address |
OTP
| Method | Path | What it does |
|---|---|---|
POST | /v1/otp/send | Send a code |
POST | /v1/otp/verify | Verify it, opening the OTP gate |
Other
| Method | Path | What it does |
|---|---|---|
POST | /v1/inbox/create | File an enquiry or message, with attachments |
GET | /v1/health | Liveness. No credentials needed. |
Back office (HMS)
For a hospital or clinic system keeping its own records in step with medos. Every route here is API-key only — a widget session is refused — and gated on your plan, one entitlement per operation. See Entitlements, and Acting user for the header every write needs.
Each page carries its own runnable request, so you can try an endpoint on the page that documents it.
Appointment and queue read-back
| Method | Path | What it does |
|---|---|---|
GET | /v1/appointments/{appointmentId} | Read one appointment back |
POST | /v1/appointments/search | Filtered appointment list. Answers 200 |
GET | /v1/appointments/schedule-slots | A practitioner's shaped day |
GET | /v1/qms-appointments/visits | Paged queue history |
GET | /v1/qms-appointments/day-visits | One day's queue |
GET | /v1/qms-appointments/shift/status | Where the queue has reached |
GET | /v1/qms-appointments/{id} | One queue visit |
Patients
| Method | Path | What it does |
|---|---|---|
GET | /v1/patients/search-by-mrn | Find a patient by medical record number |
GET | /v1/patients/search-by-email | Find a patient by email |
GET | /v1/patients | The workspace roster. Granted separately |
GET | /v1/patients/{patientId} | One patient |
GET | /v1/patients/{patientId}/visits | Visit history |
POST | /v1/patients | Create or update a patient |
Clinical records
| Method | Path | What it does |
|---|---|---|
GET | /v1/prescriptions/{id} | One prescription |
POST | /v1/prescriptions | Write a prescription |
PATCH | /v1/prescriptions/{id} | Amend one |
GET | /v1/prescriptions/{appointmentId}/pdf | The rendered PDF. Keyed by appointment |
GET | /v1/patients/{patientId}/prescriptions | A patient's, for given appointments |
POST | /v1/patients/{patientId}/vitals | Record vitals |
DELETE | /v1/patients/{patientId}/vitals/{vitalId} | Remove a reading |
POST | /v1/patients/{patientId}/medical-history | Add medical history |
GET | /v1/patients/{patientId}/documents | Documents, with presigned urls |
DELETE | /v1/patients/{patientId}/documents/{documentId} | Remove a document |
GET | /v1/medicines/search | Medicine catalogue |
Locations and configuration
| Method | Path | What it does |
|---|---|---|
GET | /v1/addresses | Locations |
GET | /v1/addresses/{addressId}/rooms | Rooms at a location |
GET | /v1/addresses/{addressId}/follow-up-policy | Follow-up rules |
GET | /v1/doctors | Practitioners, and their medos user ids |
GET | /v1/practitioner-shifts | Who is working, where, when |
GET | /v1/appointment-configs | Scheduled-appointment configuration |
GET | /v1/qms-configs | Queue configuration |
GET | /v1/booking-policy | Booking windows and cancellation rules |
GET | /v2/workspaces/payment-methods | What the clinic accepts |
Not exposed, by decision
The service and price list (/v1/offerings) is deliberately absent. Upstream
filters it by the user who created each offering rather than by workspace, so served
through an API key it would return an arbitrary subset of the clinic's catalogue — a
silently incomplete price list is worse than none. It needs a change on the medos side
first.
Document upload is a multipart endpoint and needs its own size and streaming policy; listing and deleting ship first. Consultation sessions (notes and audio) are not exposed either: consultation audio is the most sensitive payload in medos, and it deserves a deliberate decision rather than arriving as part of a batch.
There are no outbound webhooks. A cancellation made by clinic staff in the medos dashboard reaches you when you next search, so poll on a schedule rather than waiting for a callback.
Conventions used on every page
| Base URL | https://api.medos.one |
| IDs | Numeric and workspace-scoped. addressId is a workspace address (a clinic location), not a patient address. |
| Dates | YYYY-MM-DD in the clinic's own timezone |
| Times | Prefer the offset-bearing fromDateTimeIso / toDateTimeIso. The HH:mm pair is deprecated and ambiguous outside India. |
| Unknown fields | Rejected, not ignored — a typo'd body key is a 400 — except on POST /v1/patients, which drops them silently. |
| Errors | Auth failures are listed in Errors; business errors come from the Medos core unchanged. |