Two kinds of key, both made by a clinic admin inside the app and shown once.
API keys · mza_…Admin → Integrations. Each key holds named scopes and can call only the routes those scopes open. It reaches its own clinic and nothing else, expires within two years, and is limited to 600 requests a minute.
Device keys · mzv_…Voice Inbox → Integrations. For a recorder or notetaker: it can open, feed and close voice sessions and read what became of them, and nothing else.
What a key can be given. Billing and pharmacy are read-only feeds of amounts, ids, medicine names and quantities. No key can write a prescription, a note or a result, or read clinical notes or HR.
Patients · 9Find a patient, read the record your key is allowed to read, check for duplicates, and register a new patient.
✓GET/v1/patients/:patientIdThe full record needs a care relationship, not just the permission. Holding `patient.read` lets you read *a* patient, never *this* one.Scope: patient.read
✓GET/v1/patients/by-mrn/:mrnBy mrn: patients by mrn (one record)Scope: patient.read
◌POST/v1/patients/duplicate-checkCalled as the clerk types, before anything is created.Scope: patient.read· JSON body
◌POST/v1/patients/intakeRegister a patient; a strong duplicate is refused until confirmedNotDuplicate is sent.Scope: patient.intake· JSON body· 120/min
◌POST/v1/patients/intake/duplicate-checkLook for an existing record before registering; phones come back masked.Scope: patient.intake· JSON body· 120/min
✓GET/v1/registration-requestsList: registration requestsScope: patient.read· Query: status
Appointments and availability · 21Read diaries, free slots and bookings, and book, move or cancel an appointment, for a booking widget, a call centre or a calendar.
✓GET/v1/appointments/availabilityAvailability: appointments availabilityScope: appointment.read· Query: from, schedulableId, serviceType, to
✓GET/v1/scheduling/bookings/:groupId/cardOne appointment as a confirmation reads it: doctor, type, prep note, when.Scope: appointment.read
✓GET/v1/scheduling/bookings/:groupId/icsThe same appointment as a calendar file for a phone.Scope: appointment.read
✓GET/v1/scheduling/diaryThe calendar's read: a day or a week of bookings with the patient's name, the type and the state on each, for every resource at once.Scope: appointment.read· Query: facilityId, from, schedulableId, to
◌POST/v1/scheduling/intake/bookingsBook a patient of this clinic into an open slot.Scope: appointment.intake· JSON body
◌POST/v1/scheduling/intake/bookings/:groupId/cancelCancel a patient's booking, with the reason the patient gave.Scope: appointment.intake· JSON body
◌POST/v1/scheduling/intake/bookings/:groupId/rescheduleMove a patient's booking to another open slot; the old one is released.Scope: appointment.intake· JSON body
✓GET/v1/scheduling/intake/resourcesThe doctors and services a patient can be booked with.Scope: appointment.intake· Query: facilityId
✓GET/v1/scheduling/intake/slotsOpen appointment slots in a window of up to 62 days, with who they are with.Scope: appointment.intake· Query: facilityId, from, schedulableId, serviceType, to
✓GET/v1/scheduling/schedulables/:id/dayOne resource's list for one day — the clinic's working view.Scope: appointment.read· Query: date
Billing · 4Read-only, for an accounting system: bills with their lines, payments, and what each patient still owes.
✓GET/v1/billing/feed/billsBills finalised in a period, with totals, paid and balance; paged by `after`.Scope: billing.read· Query: after, from, limit, patientId, status, to
✓GET/v1/billing/feed/bills/:idOne bill: totals, its lines (service, quantity, price, tax) and its payments.Scope: billing.read
✓GET/v1/billing/feed/outstandingWhat each patient still owes on finalised bills, optionally for bills from a period.Scope: billing.read· Query: after, from, limit, patientId, to
✓GET/v1/billing/feed/paymentsPayments received in a period, with method, amount, status and receipt number.Scope: billing.read· Query: after, from, limit, patientId, to
Pharmacy and stock · 3Read-only: stock levels, batches near expiry, and prescriptions waiting to be dispensed (medicine and quantity, no clinical detail).
✓GET/v1/pharmacy/feed/dispense-queuePrescriptions waiting to be dispensed: medicine and quantity per line, patient id and MRN.Scope: pharmacy.feed.read· Query: limit
✓GET/v1/pharmacy/feed/expiringBatches on the shelf that expire within `withinDays` (default 60), or already have.Scope: pharmacy.feed.read· Query: withinDays
✓GET/v1/pharmacy/feed/stockStock per item — on hand, reorder level, low, expiring soon; filter `low` or `expiring`.Scope: pharmacy.feed.read· Query: filter
Admissions funnel · 5Read-only: report the admission pipeline to a referral partner or a dashboard.
◌POST/v1/voice/ingest/sessions/:id/segmentsAppend up to 200 segments. A segment id already stored is counted as a duplicate, not an error.Device key· JSON body· 600/min
Other · 15
✓GET/v1/calls/centre/callerCaller: calls centre callerScope: appointment.read + patient.read· Query: phone
✓GET/v1/calls/centre/slotsSlots: calls centre slotsScope: appointment.read· Query: days, near, q
✓GET/v1/calls/centre/todayToday: calls centre todayScope: appointment.read
◌POST/v1/fhir/$exportStart a bulk FHIR export of every patient: 202, with the status URL in Content-Location.Scope: fhir.read· Query: _outputFormat, _since, _type· 10/hour
✓GET/v1/fhir/$export/:jobIdPoll a bulk export: 202 while it works, then signed NDJSON links that expire.Scope: fhir.read
!DELETE/v1/fhir/$export/:jobIdCancel a bulk export and delete its files.Scope: fhir.read
✓GET/v1/fhir/Patient/:patientIdOne patient as a FHIR Patient resource.Scope: fhir.read
✓GET/v1/fhir/Patient/:patientId/$everythingThe patient's record as a searchset Bundle. `_type` narrows it. For an API key, DocumentReference entries are metadata only: their download link needs `file.read`, which no key can hold.Scope: fhir.read· Query: _type· 120/min
Generated from the same controllers as the table above, by the same build that fails when either goes stale — so neither can describe a route the code does not actually open to a key.
OpenAPI 3.1 documentEvery endpoint on this page, plus request/response shapes, security schemes and the 17 webhook events, as one JSON file. Feed it to Postman, Redocly or your own client generator.Download openapi.json
TypeScript SDK · @medappz/sdkA zero-dependency fetch client: one typed method per endpoint, bearer auth for either key kind, Idempotency-Key support, and automatic retry on 429. No build step — copy the source into your project.Download the .zip
Python SDK · medappzThe same shape over requests: one method per endpoint, typed request bodies, the same auth, idempotency and 429-retry behaviour as the TypeScript client.Download the .zip
{
"error": {
"code": "VALIDATION_FAILED",
"message": "phone must be a valid mobile number.",
"requestId": "req_01J…"
}
}
Send an Idempotency-Key header on writes so a retry is a no-op, not a duplicate. A 429 means slow down; quote the requestId when you write to us. The developer guide walks through pushing a lead and verifying a webhook signature end to end.