List bookings API with GET /api/v1/bookings
The list bookings API is GET /api/v1/bookings: it returns your business’s appointments in time order, each with its local time in its branch and its UTC instant, selected by day and by status. It needs a key with the bookings.read scope.
What does the bookings list return?
Section titled “What does the bookings list return?”It returns one page of bookings in data, from the earliest appointment to the latest, with a nextCursor for the next page, or null on the last page.
- Without
fromandto, you get every booking from the earliest, past and upcoming. - Appointments booked by the agent or your team in Mujib are included. Historical rows imported from an old register are not part of the API.
- Read bookings is offered when you create a key only if your business uses appointments.
Which parameters does it take?
Section titled “Which parameters does it take?”All parameters are optional, and any other parameter returns a 400:
| Parameter | Type | Meaning |
|---|---|---|
from | date YYYY-MM-DD | First day, included |
to | date YYYY-MM-DD | Last day, included |
status | string | One status only (see the next table) |
limit | integer | Bookings per page: 50 by default, up to 100 |
cursor | string | The previous page’s nextCursor. See cursor pagination |
fromandtoare days in each branch’s calendar and time zone, not UTC. An appointment at ten in the morning in your branch falls on its day as you see it in the dashboard.- A date must be a real day:
2026-02-31gets a 400, and so does afromafterto. - For a single day’s bookings, set
fromandtoto the same day.
status values, and what the dashboard calendar calls them:
| Value | In the dashboard |
|---|---|
requested | Pending |
confirmed | Confirmed |
cancelled | Cancelled |
completed | Attended |
no_show | No-show |
How do I send the request?
Section titled “How do I send the request?”This example asks for a month of confirmed bookings:
curl "https://api.mujib.ai/api/v1/bookings?from=2026-11-01&to=2026-11-30&status=confirmed&limit=100" \ -H "Authorization: Bearer $MUJIB_API_KEY"const url = new URL('https://api.mujib.ai/api/v1/bookings');url.searchParams.set('from', '2026-11-01');url.searchParams.set('to', '2026-11-30');url.searchParams.set('status', 'confirmed');url.searchParams.set('limit', '100');
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.MUJIB_API_KEY}` },});const body = await res.json();if (!res.ok) throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`);for (const b of body.data) console.log(b.localTime, b.branch?.name, b.customer.name);import osimport requests
res = requests.get( "https://api.mujib.ai/api/v1/bookings", params={"from": "2026-11-01", "to": "2026-11-30", "status": "confirmed", "limit": 100}, headers={"Authorization": f"Bearer {os.environ['MUJIB_API_KEY']}"}, timeout=30,)body = res.json()if not res.ok: raise RuntimeError(f"{res.status_code} {body['error']['code']}: {body['error']['message']}")for b in body["data"]: print(b["localTime"], (b["branch"] or {}).get("name"), b["customer"]["name"])To read every page to the end, use the function in cursor pagination.
What does the response look like?
Section titled “What does the response look like?”A 200. The data is made up, for a branch in Amman:
{ "data": [ { "id": "3f0c9a52-7d1e-4b8a-9c41-2e6f8a1b0d77", "status": "confirmed", "source": "agent", "service": "consultation", "startsAt": "2026-11-12T07:30:00Z", "localTime": "2026-11-12T10:30:00", "timezone": "Asia/Amman", "durationMinutes": 30, "branch": { "id": "e7f6a5b4-3c2d-4e1f-9a8b-7c6d5e4f3a21", "name": "الفرع الرئيسي" }, "specialist": "ليلى", "customer": { "contactId": "5d8f2a61-0c4e-4b7a-9f13-6e2b8c0d4a57", "name": "سارة", "phone": "962790000000" }, "createdAt": "2026-11-04T18:22:09.117Z" }, { "id": "c2a7e915-6f3b-4d80-b4e1-7a9d5c0f2b36", "status": "requested", "source": "staff", "service": "followup", "startsAt": "2026-11-12T09:00:00Z", "localTime": "2026-11-12T12:00:00", "timezone": "Asia/Amman", "durationMinutes": null, "branch": { "id": "e7f6a5b4-3c2d-4e1f-9a8b-7c6d5e4f3a21", "name": "الفرع الرئيسي" }, "specialist": null, "customer": { "contactId": null, "name": "أحمد", "phone": "0790000000" }, "createdAt": "2026-11-05T08:01:44.360Z" } ], "nextCursor": "MjAyNi0xMS0xMlQxMjowMDowMHxjMmE3ZTkxNS02ZjNiLTRkODAtYjRlMS03YTlkNWMwZjJiMzY"}Every booking always carries these fields; a field with no value comes as null:
| Field | Type | Meaning |
|---|---|---|
id | string | The booking’s stable id, for get a booking |
status | string | The booking’s status (see the table above) |
source | string | Who made it: agent, the agent in a conversation, or staff, your team in the dashboard |
service | string | The visit type’s id as your business defined it, such as consultation, not its display name. See visit types |
startsAt | UTC instant | The start in UTC, as YYYY-MM-DDTHH:MM:SSZ |
localTime | string | The start on the branch’s clock, with no offset, as YYYY-MM-DDTHH:MM:SS. This is the time the customer was given |
timezone | string | The time zone of localTime, such as Asia/Amman: the branch’s zone, else your business’s |
durationMinutes | integer or null | Length in minutes, or null when your business’s default length applies |
branch | object or null | The branch, with id and name, or null when the booking has none |
specialist | string or null | The specialist’s name, or null when none is assigned |
customer.contactId | string or null | The customer’s id for get a contact, or null for a booking without a registered customer |
customer.name | string or null | The name written on the booking, else the customer’s name |
customer.phone | string or null | The number written on the booking, else the customer’s number |
createdAt | UTC instant | When the booking was made |
What errors can it return?
Section titled “What errors can it return?”| HTTP | code | Why |
|---|---|---|
| 400 | VALIDATION_ERROR | An unknown parameter, a date not in YYYY-MM-DD or not a real day, from after to, an unknown status, a limit out of range, or a cursor that cannot be read |
| 401 | UNAUTHORIZED | No key, or a key that is not valid |
| 403 | FORBIDDEN | The key lacks bookings.read |
| 429 | RATE_LIMITED | You went over a rate limit |
| 500 | INTERNAL | An unexpected server error |
The details are in API errors and rate limits.
Frequently asked questions
Are from and to in UTC?
No. They are calendar days in each branch's own time zone, and both days are included. startsAt in the response is a UTC instant.
Do old bookings I imported from a previous register show up?
No. Historical rows imported from an old register are not part of the API. Appointments booked in Mujib are.
What does a null durationMinutes mean?
The booking carries no length of its own, so your business's default length applies.
Can the list tell me which bookings changed recently?
There is no parameter for that. Read the window of days you care about again, or use webhooks to hear about each new or cancelled booking as it happens.