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

# Patient Tracking

> Read the live patient tracking board for a practice's EHR

The patient-tracking endpoints return the practice's live tracking board: who is in clinic today, their
appointment, room, status and provider. They are **v4 only** and need the `read:patient_tracking` scope
on every route. Every response, errors included, is sent with `Cache-Control: private, no-store`.

> [!WARNING]
>
> The board is read live from the practice's EHR. The base scope returns patient initials and gender
> alongside appointment details; that is identifiable data, not anonymous data.

## Flow

1. `GET /v4/patient-tracking/sources` lists the organization's tracking sources: one per EHR
   connection the board can be read through. Each carries `sourceId` (`pts_…`), `instanceId`
   (`ins_…`), `ehr`, `availability` and `capabilities`. This call makes no EHR request.
2. `GET /v4/patient-tracking/facilities?sourceId=` and `GET /v4/patient-tracking/providers?sourceId=`
   list the native facility and provider ids to filter by.
3. Poll `GET /v4/patient-tracking/snapshot?sourceId=…` every `recommendedPollIntervalSeconds` (10).

`sourceId` must be the `pts_…` value from `/sources`; a raw UUID or another resource's id is a `400`. A
source that does not exist, belongs to another organization or is no longer eligible is a `404
source_not_found`.

## Snapshot parameters

| Parameter | Rules |
| - | - |
| `sourceId` | Required. |
| `facilityExternalIds` | Comma-separated native ids. ModMed (`capabilities.facilitySelection: "single"`) needs exactly one, otherwise `400 capability_unsupported`. EZDerm accepts several and defaults to every facility the source can read. An id outside the source is `400 facility_not_in_source`. |
| `providerExternalIds` | Optional, at most 100 after removing duplicates. ModMed matches the row's primary provider; EZDerm matches any provider role on the encounter (`capabilities.providerFilter`). An id that is neither in the source's provider list nor on any of the day's rows is `400 provider_not_in_source`. |
| `date` | Optional `YYYY-MM-DD`, defaulting to today in the source's timezone (resolved by the server). Impossible and future dates are `400`. EZDerm reads today only: any other day is `400 capability_unsupported`. |
| `include` | Optional comma-separated expansions; see below. |

Empty list elements (`101,,102`), unknown expansions and unknown query parameters are all `400`.

## Expansions

| `include` | Requires (all of) | Adds to each row |
| - | - | - |
| `patient` | `read:patients` | `patient`: native patient id, names, date of birth, MRN, sex, gender |
| `contact` | `read:patients`, `read:patient_pii` | `contact`: phone, email |
| `visitDetails` | `read:appointments` | `visitDetails`: chief complaint, payment method |
| `insurance` | `read:patients`, `read:insurance_policies` | `insurance`: primary insurance name, copay amount |

Requesting an expansion without every listed scope is a `403 include_not_permitted`; it is never silently
dropped. An expansion you did not request is absent from the row, not `null`. Inside an expansion, a value
the EHR does not supply is `null`.

## Snapshot response

* `rows`: the whole day for the selected facilities, with no pagination. On EZDerm a row is an encounter in
  one of seven in-clinic statuses (`CHECKED_IN`, `ARRIVED`, `IN_ROOM`, `WITH_PROVIDER`, `WITH_STAFF`,
  `READY_FOR_STAFF`, `READY_FOR_PROVIDER`). `trackingKey` is a stable row identity across polls.
* `counts`: `returned` is the number of rows. On ModMed, `seenAppointments` also counts the returned rows
  (after the provider filter) and `scheduledAppointments` counts the facility's scheduled appointments
  regardless of provider. EZDerm reports both as `null`.
* `freshness.state`: `fresh`, or `stale` when the latest EHR read failed and a recent complete snapshot
  (no older than `maxUsableAgeSeconds`) was served instead.
* `completeness`: per-component status (`primary`, `officeFlow`, `colors`) and warning codes. A snapshot
  is only returned when its primary read was complete.
* `access`: the expansions requested and returned.

## Errors

| Status | `code` | Meaning |
| - | - | - |
| 400 | `capability_unsupported` | The source's EHR cannot serve this request (facility count, past date on EZDerm). |
| 400 | `facility_not_in_source`, `provider_not_in_source` | A filter id the source does not know. A filter is never dropped or widened. |
| 403 | `include_not_permitted` | An expansion lacks one of its scopes. |
| 404 | `source_not_found` | Unknown, other-organization or ineligible source. |
| 503 | `source_unavailable` | The connection cannot be read now (for example paused, or failing EHR authentication); `data.reason` says why. |
| 503 | `catalogue_unavailable` | The EHR's facility or provider list could not be read completely. |
| 503 | `snapshot_unavailable` | No complete snapshot could be read, and none recent enough to serve stale. |

Every `503` sets `Retry-After` and repeats it as `data.retryAfterSeconds`.


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