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

# Manage patients

> Search, read, create, update and archive patients' administrative data through the REST API.

The patient operations cover administrative data: name, contact details, birth date, codes and status. Clinical history and notes are not in the API yet.

## Before you start

* The clinic's `patients` [data area](https://docs.brelio.com/en/concepts/data-areas.md) is on, and patient-data access was accepted for your credential. Otherwise every call here answers `403 DATA_AREA_OFF` or `403 PATIENT_DATA_CONSENT_REQUIRED`.
* Your key holds `patients.administrative.read`, and `.create`, `.update` or `.archive` for the writes.
* Every patient record you receive counts toward the [2,000 records per hour](https://docs.brelio.com/en/concepts/rate-limits.md) ceiling of your credential.

```bash theme={null}
export BRELIO_API_KEY="…"
export BRELIO=https://api.brelio.app/v1
```

## Search

`search` matches name, email, phone, patient code, internal code or ID number, the same as Brelio's search box:

```bash theme={null}
curl -s "$BRELIO/patients?search=ana&limit=10" \
  -H "Authorization: Bearer $BRELIO_API_KEY"
```

```json Response theme={null}
{
  "data": [
    {
      "id": "c588eb77-12e8-4042-8cce-48fb0555408f",
      "code": "PAC-0001",
      "firstName": "Ana",
      "lastName": "Pérez",
      "birthDate": null,
      "sex": null,
      "email": "ana.perez@example.com",
      "phone": null,
      "status": "active",
      "identificationNumber": null,
      "identificationType": "dni",
      "internalCode": null,
      "responsibleId": null,
      "admittedAt": null,
      "lastSessionAt": null,
      "nextSessionAt": null,
      "archivedAt": null,
      "version": "2026-11-09 17:59:08.46+00",
      "createdAt": "2026-11-09T17:59:08.460Z",
      "updatedAt": "2026-11-09T17:59:08.460Z"
    }
  ],
  "next_cursor": null,
  "has_more": false
}
```

Filter by `status` (`active`, `inactive`, `discharged`). Results are sorted by last name and [paginated](https://docs.brelio.com/en/concepts/pagination.md).

## Read one

```bash theme={null}
curl -s "$BRELIO/patients/$PATIENT_ID" \
  -H "Authorization: Bearer $BRELIO_API_KEY"
```

## Create

Search first so you do not create a duplicate. Only `firstName` is required.

```bash theme={null}
curl -s -X POST "$BRELIO/patients" \
  -H "Authorization: Bearer $BRELIO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "firstName": "Laura",
    "lastName": "Serra",
    "birthDate": "1990-05-14",
    "email": "laura.serra@example.com",
    "phone": "+34 600 123 456"
  }'
```

```json 201 Created theme={null}
{
  "id": "d4ddb883-ee85-46d1-9719-5e0f7e585392",
  "code": "PAC-0003",
  "firstName": "Laura",
  "lastName": "Serra",
  "birthDate": "1990-05-14",
  "email": "laura.serra@example.com",
  "phone": "+34 600 123 456",
  "status": "active",
  "version": "2026-11-09 17:59:58.817+00",
  "…": "…"
}
```

* `sex` takes `male`, `female` or `other`.
* `centerId` links the patient to a center; it defaults to the clinic's default center.
* The same plan limits as the web apply, such as the active-patient limit.

## Update

Send only the fields that change, with the `version` you read as `expectedVersion`. `null` clears a field; `lastName` cannot be cleared.

```bash theme={null}
curl -s -X PATCH "$BRELIO/patients/$PATIENT_ID" \
  -H "Authorization: Bearer $BRELIO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "expectedVersion": "2026-11-09 17:59:58.817+00",
    "phone": "+34 600 765 432",
    "email": null
  }'
```

The answer is the updated patient with a new `version`. A stale `expectedVersion` answers `409 VERSION_CONFLICT`; read the patient again. See [concurrency](https://docs.brelio.com/en/concepts/concurrency.md).

## Archive

Archiving retires a patient: it disappears from lists and searches, and `GET /v1/patients/{id}` answers `404 PATIENT_NOT_FOUND`, but its history is kept and it can be restored in Brelio.

```bash theme={null}
curl -s -X POST "$BRELIO/patients/$PATIENT_ID/archive" \
  -H "Authorization: Bearer $BRELIO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"expectedVersion": "2026-11-09 17:59:58.866+00"}'
```

```json Response theme={null}
{ "id": "d4ddb883-…", "status": "active", "archivedAt": "2026-11-09T17:59:58.967Z", "version": "2026-11-09 17:59:58.967+00", "…": "…" }
```

`status` and `archivedAt` are independent: an archived patient keeps its last status. There is no delete.

## Sync patients into another system

```python sync_patients.py theme={null}
import os
import requests

BASE = "https://api.brelio.app/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BRELIO_API_KEY']}"}


def patients(**filters):
    cursor = None
    while True:
        params = {**filters, "limit": 100, **({"cursor": cursor} if cursor else {})}
        response = requests.get(f"{BASE}/patients", params=params, headers=HEADERS, timeout=10)
        if response.status_code == 429:
            raise RuntimeError(f"Rate limited; retry in {response.headers['Retry-After']} s")
        response.raise_for_status()
        page = response.json()
        yield from page["data"]
        if not page["has_more"]:
            return
        cursor = page["next_cursor"]


for patient in patients(status="active"):
    print(patient["code"], patient["firstName"], patient["lastName"], patient["email"])
```

Schedule it for quiet hours and keep the 2,000 records per hour ceiling in mind for large clinics.


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