Pack catalog
The session packs a clinic sells — prices, session counts, validity and which doctors accept them.
GET /v1/session/packsA session pack is a block of visits bought up front — ten physiotherapy
sessions, six follow-ups — that the patient then draws down. This lists the
packs the clinic has configured, which is where packageConfigId comes from for
every purchase route.
No parameters, no OTP. The workspace comes from your key.
Try it
/v1/session/packsGET /v1/session/packshttps://api.medos.oneUse a dedicated test key, and put your browser's address on its allowlist
A Developer API key authenticates on its own, so it only works from the addresses registered against it — and this page calls from your browser, not your servers. Unless your own public address is on the list you get a 403 naming it, which is the allowlist doing its job. Your browser may also reach us over IPv6 even when your server does not, so the address in the error is often not the one you expected. The key here is kept in memory only and never written to storage, but create a test key for it and deactivate that key when you are done.
Request
curl -s "https://api.medos.one/v1/session/packs" \
-H "x-api-key: $MEDOS_API_KEY"Response
{
"status": "Success",
"data": {
"sessionPacks": {
"list": [
{
"id": 12,
"workspaceId": 1,
"packageName": "Physio — 10 sessions",
"description": "<p>Ten 30-minute sessions</p>",
"totalSessions": 10,
"packagePrice": 5000,
"discount": 10,
"discountType": "PERCENTAGE",
"discountedPrice": 4500,
"validityDays": 90,
"durationMins": 30,
"allowedConsultationModes": ["OFFLINE"],
"doctorIds": [4, 7],
"isAllDoctorsAllowed": false,
"allowFamilyBooking": true,
"maxFamilyMembers": 3,
"isActive": true,
"hiddenFromSelfBooking": false,
"internationalPackagesPricing": [
{ "id": 3, "currency": "USD", "amount": 60, "discount": 0 }
]
}
],
"count": 4
},
"sessionPacksAnalytics": {}
}
}| Field | Meaning |
|---|---|
id | The packageConfigId every purchase route takes. |
discountedPrice | What the patient actually pays — send this as packageAmount. packagePrice is the pre-discount figure. |
totalSessions / validityDays | How many visits, and how long they last from purchase. |
durationMins | The session length. A booking that spends this pack must match it. |
doctorIds / isAllDoctorsAllowed | Which practitioners accept the pack. When isAllDoctorsAllowed is true, doctorIds is not the limit. |
allowedConsultationModes | The modes the pack covers. |
internationalPackagesPricing[] | Per-currency pricing for patients billed internationally. |
hiddenFromSelfBooking | The clinic sells this one at the counter only. Respect it in a patient-facing flow. |
isActive | Retired packs stay in the list. Filter these out before showing them. |
count | Total packs configured, for paging context. Up to 100 come back in one call. |
description is raw HTML
It is stored as rich text and returned as stored. Sanitise it before rendering it in a browser.
Where to go with a packageConfigId
| Goal | Route |
|---|---|
| Sell a pack on its own, paid online | Buy a pack |
| Sell a pack and book the first visit together | book-appointment-unified with bookingType: "PACKAGE_PURCHASE" |
| Spend a pack the patient already owns | book-appointment-unified with bookingType: "USE_ACTIVE_PACKAGE" |
A patient's existing packs are not here — read those from search-by-phone.