# Health: registries and statistics

> EMA medicines, NPPES providers, ClinicalTrials.gov, FDA 510(k) summaries, WHO GHO and Eurostat mortality.

Page: https://docs.aggre.org/api/data/health-registries · Section: API reference · All pages: https://docs.aggre.org/llms.txt

Registries and statistics from health authorities. See the [health guide](https://docs.aggre.org/datasets/health.md).

On this page:

- [EMA medicines register](#listEmaMedicines): `GET /v1/health/drugs/ema_medicines`
- [One EMA medicine, with its text and source row](#getEmaMedicine): `GET /v1/health/drugs/ema_medicines/{product_number}`
- [Search the NPPES NPI Registry](#searchNppesProviders): `GET /v1/health/providers/nppes`
- [One NPPES provider by NPI](#getNppesProvider): `GET /v1/health/providers/nppes/{npi}`
- [ClinicalTrials.gov studies](#listTrialsStudies): `GET /v1/health/trials/clinicaltrials_gov`
- [One ClinicalTrials.gov study, with its prose](#getTrialsStudy): `GET /v1/health/trials/clinicaltrials_gov/{nct_id}`
- [WHO Global Health Observatory observations of one indicator](#listWhoObservations): `GET /v1/health/statistics/who_gho`
- [The curated WHO GHO indicators](#listWhoIndicators): `GET /v1/health/statistics/who_gho/indicators`
- [Eurostat causes of death, cells of one cause](#listEurostatMortality): `GET /v1/health/statistics/eurostat_mortality`
- [Cause codes in the Eurostat table](#listEurostatCauses): `GET /v1/health/statistics/eurostat_mortality/causes`
- [Place codes in the Eurostat table](#listEurostatPlaces): `GET /v1/health/statistics/eurostat_mortality/places`
- [One Eurostat cell](#getEurostatMortality): `GET /v1/health/statistics/eurostat_mortality/{year}/{geo}/{icd10}`

## EMA medicines register {#listEmaMedicines}

`GET /v1/health/drugs/ema_medicines`

Centrally authorised human and veterinary medicines, one row per EMA product number, withdrawn and refused ones included; a medicine the newest report no longer contains has `in_latest_report: false`. Ordered by `(updated_at, product_number)` ascending, so `updated_since` plus the cursor is a change feed. The list leaves out `therapeutic_indication` and `raw` unless `include=text`. 503 `terms_unread` until a person has read EMA's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `category` | query | no | string | Exact, as published (human or veterinary). |
| `status` | query | no | string | Exact, as published (e.g. Authorised, Withdrawn). |
| `active_substance` | query | no | string | Exact, as published. |
| `atc_code` | query | no | string, pattern `^[A-Za-z0-9]{1,7}$` | Prefix of the ATC code, 1-7 letters or digits (case-insensitive). |
| `therapeutic_area` | query | no | string | Exact, as published. |
| `accelerated_assessment` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `additional_monitoring` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `advanced_therapy` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `biosimilar` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `conditional_approval` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `exceptional_circumstances` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `generic` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `orphan` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `prime` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. |
| `authorised_since` | query | no | string, date | YYYY-MM-DD on `authorisation_date`. |
| `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. |
| `include` | query | no | `text` | `text` adds the long fields the list leaves out (smaller page cap). |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000, or 1-200 with `include=text`. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/ema_medicines?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_ema_medicine`](https://docs.aggre.org/api/schemas.md#health_ema_medicine).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One EMA medicine, with its text and source row {#getEmaMedicine}

`GET /v1/health/drugs/ema_medicines/{product_number}`

Every column, `therapeutic_indication` and `raw` (every cell of the report row) included. A withdrawn medicine is still found. Takes no query parameters. 503 `terms_unread` until a person has read EMA's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `product_number` | path | yes | string | EMA product number as published (opaque, 1-64 characters). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/ema_medicines/<product_number>" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_ema_medicine`](https://docs.aggre.org/api/schemas.md#health_ema_medicine).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Search the NPPES NPI Registry {#searchNppesProviders}

`GET /v1/health/providers/nppes`

Providers of the NPPES NPI Registry, one row per NPI, as the worker projected them (practice location, no mailing address, no phone numbers). These are records about named individuals, so this is a **search, not an enumeration**: give `npi` (up to 20, comma-separated), or `state` together with `last_name`, `organization_name` (a prefix of at least 3 characters) or `taxonomy`; anything less is 400. Ordered by NPI, at most 100 a page (default 25); there is no change feed and no bulk route. Names match case-insensitively, `state` and `taxonomy` exactly. `meta.status` is `not_loaded` until a monthly baseline has been applied and `degraded` while a gap in the weekly files is unrepaired; `meta.load` says what has been applied. 503 `terms_unread` until a person has read CMS's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `npi` | query | no | string | One or more NPIs, comma-separated (at most 20), each exactly 10 digits. |
| `last_name` | query | no | string | Legal last name, case-insensitive exact. Needs `state`. |
| `first_name` | query | no | string | Legal first name, case-insensitive exact. Narrows `last_name`; not allowed without it. |
| `organization_name` | query | no | string | Prefix of the legal business name, case-insensitive, at least 3 characters. Needs `state`. |
| `taxonomy` | query | no | string, pattern `^[A-Za-z0-9]{10}$` | The 10-character NUCC taxonomy code of the primary taxonomy (case-insensitive). Needs `state`. |
| `state` | query | no | string, pattern `^[A-Za-z]{2}$` | Two-letter practice-location state code (case-insensitive). |
| `deactivated` | query | no | boolean | `true`: only NPIs with a deactivation date; `false`: only those without. Narrows a search; it is not one by itself. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–100, default `25` | Rows per page: 1-100. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/providers/nppes?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_nppes_provider`](https://docs.aggre.org/api/schemas.md#health_nppes_provider).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One NPPES provider by NPI {#getNppesProvider}

`GET /v1/health/providers/nppes/{npi}`

Every stored column. Takes no query parameters. 404 for an NPI we do not hold (`meta.load` says what has been applied). 503 `terms_unread` until a person has read CMS's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `npi` | path | yes | string, pattern `^[0-9]{10}$` | A National Provider Identifier: exactly 10 digits. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/providers/nppes/<npi>" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_nppes_provider`](https://docs.aggre.org/api/schemas.md#health_nppes_provider).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## ClinicalTrials.gov studies {#listTrialsStudies}

`GET /v1/health/trials/clinicaltrials_gov`

Studies of the ClinicalTrials.gov registry as the worker projected them, one row per NCT id. Ordered by `(updated_at, nct_id)` ascending, so `updated_since` plus the cursor is a change feed. The three prose fields (`brief_summary`, `detailed_description`, `eligibility_criteria`) are left out unless `include=prose`, and the page is then capped at 100. List filters (`phase`, `condition`, `country`) match one element of the study's array exactly as published (case-sensitive). `meta.status` is `backfilling` until the first full read of the registry has completed. 503 `terms_unread` until a person has read the registry's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `overall_status` | query | no | string | Exact, as published (e.g. RECRUITING, COMPLETED). |
| `study_type` | query | no | string | Exact, as published (e.g. INTERVENTIONAL). |
| `phase` | query | no | string | One phase as published (e.g. PHASE2); a study of two phases matches either. |
| `sponsor` | query | no | string | Exact `lead_sponsor`, as published. |
| `condition` | query | no | string | One element of `conditions`, exactly as published. |
| `country` | query | no | string | One element of `location_countries`, exactly as published (e.g. France). |
| `has_results` | query | no | boolean | Whether the registry holds results for the study. |
| `first_post_since` | query | no | string, date | YYYY-MM-DD on `first_post_date` (inclusive). |
| `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. |
| `include` | query | no | `prose` | `prose` adds the three long text fields the list leaves out (page cap 100). |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000, or 1-100 with `include=prose`. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/trials/clinicaltrials_gov?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_trials_study`](https://docs.aggre.org/api/schemas.md#health_trials_study).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One ClinicalTrials.gov study, with its prose {#getTrialsStudy}

`GET /v1/health/trials/clinicaltrials_gov/{nct_id}`

Every column but the worker's own hash, the prose fields included. Takes no query parameters. 404 for a study we do not hold (the worker reads the registry in stages; `meta.walk` says how far). 503 `terms_unread` until a person has read the registry's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `nct_id` | path | yes | string, pattern `^[A-Za-z0-9_-]{1,32}$` | ClinicalTrials.gov study id as published (letters, digits, `_` and `-`, at most 32 characters), e.g. `NCT00000102`. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/trials/clinicaltrials_gov/NCT00000102" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_trials_study`](https://docs.aggre.org/api/schemas.md#health_trials_study).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## WHO Global Health Observatory observations of one indicator {#listWhoObservations}

`GET /v1/health/statistics/who_gho`

Observations of one curated indicator (the whole table is far too large to page as one), ordered by `(spatial_dim, year, breakdown_key)` within one `spatial_dim_type` (default `COUNTRY`; regions and the world are other types). Rows the indicator's last complete read no longer contained are returned with `in_latest_read: false`. `value_display` is WHO's own formatted string. 404 `not_found` for an indicator not in the catalogue; 503 `terms_unread` until a person has read WHO's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `indicator` | query | yes | string, pattern `^[A-Za-z0-9_.-]{1,64}$` | Our indicator id (`life_expectancy`) or its GHO code (`WHOSIS_000001`); see the catalogue. |
| `spatial_dim_type` | query | no | string, pattern `^[A-Za-z0-9_.-]{1,64}$`, default `COUNTRY` | COUNTRY (default), GLOBAL, REGION, UNSDGREGION, … as published. |
| `spatial_dim` | query | no | string, pattern `^[A-Za-z0-9_.-]{1,64}$` | One place code as published (an ISO country code for COUNTRY). |
| `breakdown` | query | no | string | Dimension filter, `TYPE:value` pairs separated by commas, at most three, e.g. `SEX:SEX_MLE`. A row matches when its `breakdown` contains every pair. |
| `year_from` | query | no | integer, 1900–2100 | First year, 1900-2100. |
| `year_to` | query | no | integer, 1900–2100 | Last year, 1900-2100. |
| `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/statistics/who_gho?indicator=<indicator>&limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_who_observation`](https://docs.aggre.org/api/schemas.md#health_who_observation).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## The curated WHO GHO indicators {#listWhoIndicators}

`GET /v1/health/statistics/who_gho/indicators`

The catalogue: id, GHO code, category, Aggre's own description, whether the indicator is read page by page, and when its last complete read ended and how many rows it held. Takes no query parameters. 503 `terms_unread` until a person has read WHO's terms.

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/statistics/who_gho/indicators" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_who_indicator`](https://docs.aggre.org/api/schemas.md#health_who_indicator).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Eurostat causes of death, cells of one cause {#listEurostatMortality}

`GET /v1/health/statistics/eurostat_mortality`

Cells of one cause code (`icd10` is required: without it the list would be a dump of ~600k cells), ordered by `(updated_at, year, geo)`, so `updated_since` plus the cursor is a change feed. A cell the last complete read of its year no longer held has `in_latest_read: false`. `value` is null for a status-only cell. `meta.years` carries the dataset's own `updated` text per year read. 503 `terms_unread` until a person has read Eurostat's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `icd10` | query | yes | string, pattern `^[A-Za-z0-9_-]{1,32}$` | One cause code as published (`C33_C34`, `A-R_V-Y`, …); the causes route lists them. |
| `geo` | query | no | string | Exact Eurostat place codes, comma-separated, at most 20 (`DE,DE21,EU27_2020`). |
| `geo_kind` | query | no | `country` \| `nuts2` \| `aggregate` \| `other` | Our derived kind of place: country (two letters), nuts2 (two letters plus two characters), aggregate (EU…, EA…, EFTA…) or other. Derived by Aggre from the code's shape, not by Eurostat. |
| `year` | query | no | integer, 1900–2100 | One year; cannot be combined with year_from or year_to. |
| `year_from` | query | no | integer, 1900–2100 |  |
| `year_to` | query | no | integer, 1900–2100 |  |
| `status` | query | no | string, pattern `^[A-Za-z0-9_]{1,32}$` | Eurostat's flag, exactly as published. |
| `has_value` | query | no | boolean | `true`: only cells with a value; `false`: only status-only cells. |
| `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality?icd10=<icd10>&limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_mortality`](https://docs.aggre.org/api/schemas.md#health_eurostat_mortality).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Cause codes in the Eurostat table {#listEurostatCauses}

`GET /v1/health/statistics/eurostat_mortality/causes`

The cause codes present in the table with their labels, derived from the table. Takes no query parameters. 503 `terms_unread` until a person has read Eurostat's terms.

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality/causes" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_cause`](https://docs.aggre.org/api/schemas.md#health_eurostat_cause).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Place codes in the Eurostat table {#listEurostatPlaces}

`GET /v1/health/statistics/eurostat_mortality/places`

The place codes present in the table with their labels and our derived `geo_kind`. 503 `terms_unread` until a person has read Eurostat's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `geo_kind` | query | no | `country` \| `nuts2` \| `aggregate` \| `other` | Our derived kind of place: country (two letters), nuts2 (two letters plus two characters), aggregate (EU…, EA…, EFTA…) or other. Derived by Aggre from the code's shape, not by Eurostat. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality/places" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_place`](https://docs.aggre.org/api/schemas.md#health_eurostat_place).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One Eurostat cell {#getEurostatMortality}

`GET /v1/health/statistics/eurostat_mortality/{year}/{geo}/{icd10}`

The cell of one year, place and cause. Takes no query parameters. 503 `terms_unread` until a person has read Eurostat's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `year` | path | yes | integer, 1900–2100 |  |
| `geo` | path | yes | string | Eurostat place code. |
| `icd10` | path | yes | string | Cause code. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality/1/<geo>/<icd10>" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_mortality`](https://docs.aggre.org/api/schemas.md#health_eurostat_mortality).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).
