> ## 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.

# Making Requests

> The proper way to call the Healos External API, end to end

# Making Requests

Every call to the Healos External API follows the same pattern. Read this once,
and the rest of the [API Reference](/api-reference) is just details.

## Request Anatomy

```
METHOD  {base_url}/{resource}[/{id}]
        X-API-Key: hlsk_your_key_here
        Content-Type: application/json   ← writes only
        { ...json body... }              ← writes only
```

* **Base URL**: `https://api.healos.ai/ext-api/v1` (or
  `http://localhost:8787/ext-api/v1` in local development).
* **`X-API-Key`** is required on every request. See [Authentication](/authentication).
* **`Content-Type: application/json`** is required for `POST`, `PATCH`, and `PUT`.

## Your First Call — List Patients

```bash theme={null}
curl https://api.healos.ai/ext-api/v1/patients \
  -H "X-API-Key: hlsk_your_key_here"
```

Response:

```json theme={null}
{
  "data": [
    {
      "id": "1743552000000",
      "name": "Maria Santos",
      "created_at": "2026-03-15T09:30:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total_pages": 1
  }
}
```

<Note>
  Patient `id` is a BigInt serialized as a string. Always treat it as an
  opaque string — don't parse it as a number, and don't assume a length.
</Note>

## Pagination

List endpoints accept `page` and `limit` query parameters. Defaults are
`page=1` and `limit=20`. Use `meta.total_pages` to know when you've reached
the end.

```bash theme={null}
curl "https://api.healos.ai/ext-api/v1/patients?page=2&limit=50" \
  -H "X-API-Key: hlsk_your_key_here"
```

## Creating a Resource

Write endpoints take a JSON body. The schema for each body is in the
[API Reference](/api-reference) — stick to the documented fields. Extra
fields are rejected with a `400` validation error.

```bash theme={null}
curl https://api.healos.ai/ext-api/v1/patients \
  -H "X-API-Key: hlsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Maria Santos"}'
```

Response (`201 Created`):

```json theme={null}
{
  "data": {
    "id": "1743552000000",
    "name": "Maria Santos",
    "created_at": "2026-03-15T09:30:00.000Z",
    "pronouns": null,
    "notes": null,
    "consent": false
  }
}
```

<Note>
  `POST`, `PATCH`, and `DELETE` require a `*:write` scope for the resource.
  A key without it gets a `403`. See [Authentication → Scopes](/authentication#scopes).
</Note>

## Reading One Resource By ID

```bash theme={null}
curl https://api.healos.ai/ext-api/v1/patients/1743552000000 \
  -H "X-API-Key: hlsk_your_key_here"
```

You can grab a patient's ID from the Healos web app — it's shown as a
copy-to-clipboard badge next to the patient name in the visit and record
headers.

<Note>
  A `404` on a specific ID may mean the resource does not exist **or**
  belongs to another user. This is intentional — see [Error Handling](/errors).
</Note>

## External IDs

Patients, appointments, and documents accept an optional `external_id` on
create — a caller-supplied identifier (up to 255 characters) that lets you
correlate Healos records with rows in your own system without storing the
Healos `id`.

```bash theme={null}
curl https://api.healos.ai/ext-api/v1/patients \
  -H "X-API-Key: hlsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Maria Santos", "external_id": "PARTNER-12345"}'
```

`external_id` is **unique per organization** and **immutable** once set:

* Sending `external_id` on `PATCH` is silently ignored.
* Sending a value another record in the same org already uses returns
  `409 Conflict` with the existing record so you can reconcile:

  ```json theme={null}
  {
    "error": "external_id already in use",
    "existing": {
      "id": "481926357104938271",
      "external_id": "PARTNER-12345"
    }
  }
  ```

For document uploads (`multipart/form-data`), pass `external_id` as a form
field alongside `file` and `patient_id`.

### Lookup by external\_id

List endpoints accept `external_id=<value>` as a query parameter. The
response is the standard list shape — a one-item `data` array on hit, or
`404` on miss — so you can use the same client code as paginated listing.

```bash theme={null}
curl "https://api.healos.ai/ext-api/v1/patients?external_id=PARTNER-12345" \
  -H "X-API-Key: hlsk_your_key_here"
```

<Note>
  Documents are scoped to a patient, so the lookup path is
  `/patients/{patientId}/documents?external_id=...`.
</Note>

## Handling Responses

| Status | What it means                                                           | Where to look                                     |
| ------ | ----------------------------------------------------------------------- | ------------------------------------------------- |
| `2xx`  | Success. Body is `{ "data": ... }`, list endpoints also include `meta`. | —                                                 |
| `400`  | Validation error. Body includes a `details` map of field errors.        | [Error Handling](/errors)                         |
| `401`  | Missing, invalid, expired, or revoked key.                              | [Authentication](/authentication)                 |
| `403`  | Key is valid but lacks the required scope.                              | [Authentication → Scopes](/authentication#scopes) |
| `404`  | Resource not found (or not yours).                                      | [Error Handling](/errors)                         |
| `429`  | Rate limit exceeded. Honor the `Retry-After` header.                    | [Rate Limiting](/rate-limiting)                   |

Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and
`X-RateLimit-Reset` so you can pace yourself without waiting for a `429`.

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/api-reference">
    Full endpoint listing with request and response schemas
  </Card>

  <Card title="Authentication" icon="key" href="/authentication">
    API keys, scopes, and security best practices
  </Card>
</CardGroup>
