> ## Documentation Index
> Fetch the complete documentation index at: https://docs.healos.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Appointments for a date range

> List every appointment between two dates, one day at a time

Use this to pull a week's schedule into your system, or to reconcile HealOS
appointments with yours.

| | |
| - | - |
| **Scope** | `appointments:read` |
| **Cost** | Free |
| **Outside systems** | None. Reads appointments stored in HealOS. |
| **Safety** | Read-only and safe to retry. |

> [!WARNING]
>
> Filter with `date=YYYY-MM-DD`, one day per request. `GET /appointments`
> accepts `start_date` and `end_date`, but does not apply them today: a
> request with only those parameters returns every appointment.

## How the filter works

* `date` matches appointments whose `start_at` falls on that calendar day in
  **UTC**. An appointment at 6 PM Pacific on 14 April is 01:00 UTC on 15 April,
  so it appears under `date=2026-04-15`.
* Results are paginated (`page`, `limit` up to 100), newest `start_at` first.
* Appointments are those in HealOS: created through the API or the dashboard.
  Appointments that exist only in your EHR are not listed.

## Steps

**1. Ask for one day**

```bash theme={null}
curl "https://api.healos.ai/ext-api/v1/appointments?date=2026-04-15&limit=100" \
  -H "X-API-Key: $HEALOS_API_KEY"
```

**Expect** `200` with `data` (the appointments) and `meta`
(`page`, `limit`, `total_pages`).

**2. Read every page**

While `meta.page` is less than `meta.total_pages`, ask again with
`page=2`, `page=3` and so on.

**3. Repeat for each day in the range**

Move the `date` forward one day at a time until the end of the range. To
cover a whole local day, also fetch the UTC day after it and keep only the
appointments whose `start_at` falls inside your local day.

## Script

Node.js 18 or later: `HEALOS_API_KEY=hlsk_... node appointments.mjs 2026-04-13 2026-04-19`.

```javascript appointments.mjs theme={null}
const BASE = "https://api.healos.ai/ext-api/v1";
const [from, to] = process.argv.slice(2); // YYYY-MM-DD, inclusive, UTC days

async function getPage(date, page) {
  const url = `${BASE}/appointments?date=${date}&limit=100&page=${page}`;
  const res = await fetch(url, { headers: { "X-API-Key": process.env.HEALOS_API_KEY } });
  if (res.status === 429) {
    const wait = Number(res.headers.get("Retry-After") ?? 60);
    await new Promise((r) => setTimeout(r, wait * 1000));
    return getPage(date, page);
  }
  if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
  return res.json();
}

const all = [];
for (let d = new Date(`${from}T00:00:00Z`); d <= new Date(`${to}T00:00:00Z`); d.setUTCDate(d.getUTCDate() + 1)) {
  const date = d.toISOString().slice(0, 10);
  for (let page = 1; ; page++) {
    const { data, meta } = await getPage(date, page);
    all.push(...data);
    if (page >= meta.total_pages) break;
  }
}
console.log(`${all.length} appointments`);
for (const a of all) console.log(a.start_at, a.status, a.patient_name, a.appointment_type);
```

## Expected outcomes

| Case | Expected result |
| - | - |
| A day with appointments | `200`, `data` holds them, newest first |
| A day with none | `200`, `data: []`, `meta.total_pages: 1` |
| More than about 60 requests in a minute | `429` with `Retry-After`; the script waits and retries |
| Key without `appointments:read` | `403` `Insufficient scope. Required: appointments:read` |

Each appointment carries `id`, `patient_id`, `patient_name`, `provider_id`,
`provider_name`, `appointment_type`, `visit_type`, `start_at`,
`duration_minutes`, `status` (`SCHEDULED`, `COMPLETED`, `CANCELLED` or
`NO_SHOW`), `notes`, `repeat_rule` and your `external_id`. See
[List appointments](https://docs.healos.ai/api-reference/appointments/list-appointments.md) for the
full schema.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.