# Health: openFDA

> The 19 openFDA datasets (drug labels, NDC, approvals, shortages, recalls, device clearances and more).

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

Each openFDA dataset has the same two routes: a list (`/v1/health/{drugs|devices}/fda_{name}`) and a record (`.../fda_{name}/{key}`). Rows keep the upstream record whole in `payload`. See the [health guide](https://docs.aggre.org/datasets/health.md).

On this page:

- [FDA 510(k) summary documents (extracted text)](#listFdaSummaries): `GET /v1/health/devices/fda_510k_summary`
- [One 510(k) summary, with its text](#getFdaSummary): `GET /v1/health/devices/fda_510k_summary/{k_number}`
- [openFDA drug labels (prescribing information)](#listFdaLabel): `GET /v1/health/drugs/fda_label`
- [One record of: openFDA drug labels (prescribing information)](#getFdaLabel): `GET /v1/health/drugs/fda_label/{key}`
- [openFDA National Drug Code directory](#listFdaNdc): `GET /v1/health/drugs/fda_ndc`
- [One record of: openFDA National Drug Code directory](#getFdaNdc): `GET /v1/health/drugs/fda_ndc/{key}`
- [openFDA Drugs@FDA approvals](#listFdaDrugsfda): `GET /v1/health/drugs/fda_drugsfda`
- [One record of: openFDA Drugs@FDA approvals](#getFdaDrugsfda): `GET /v1/health/drugs/fda_drugsfda/{key}`
- [openFDA Orange Book](#listFdaOrangebook): `GET /v1/health/drugs/fda_orangebook`
- [One record of: openFDA Orange Book](#getFdaOrangebook): `GET /v1/health/drugs/fda_orangebook/{key}`
- [openFDA drug shortages](#listFdaShortages): `GET /v1/health/drugs/fda_shortages`
- [One record of: openFDA drug shortages](#getFdaShortages): `GET /v1/health/drugs/fda_shortages/{key}`
- [openFDA NDC SPL data elements (NSDE)](#listFdaNsde): `GET /v1/health/drugs/fda_nsde`
- [One record of: openFDA NDC SPL data elements (NSDE)](#getFdaNsde): `GET /v1/health/drugs/fda_nsde/{key}`
- [openFDA UNII substance identifiers](#listFdaUnii): `GET /v1/health/drugs/fda_unii`
- [One record of: openFDA UNII substance identifiers](#getFdaUnii): `GET /v1/health/drugs/fda_unii/{key}`
- [openFDA substance data](#listFdaSubstance): `GET /v1/health/drugs/fda_substance`
- [One record of: openFDA substance data](#getFdaSubstance): `GET /v1/health/drugs/fda_substance/{key}`
- [openFDA historical documents](#listFdaHistoricaldocument): `GET /v1/health/drugs/fda_historicaldocument`
- [One record of: openFDA historical documents](#getFdaHistoricaldocument): `GET /v1/health/drugs/fda_historicaldocument/{key}`
- [openFDA drug enforcement reports (recalls)](#listFdaEnforcement): `GET /v1/health/drugs/fda_enforcement`
- [One record of: openFDA drug enforcement reports (recalls)](#getFdaEnforcement): `GET /v1/health/drugs/fda_enforcement/{key}`
- [openFDA complete response letters](#listFdaCrl): `GET /v1/health/drugs/fda_crl`
- [One record of: openFDA complete response letters](#getFdaCrl): `GET /v1/health/drugs/fda_crl/{key}`
- [openFDA 510(k) clearances](#listFda510k): `GET /v1/health/devices/fda_510k`
- [One record of: openFDA 510(k) clearances](#getFda510k): `GET /v1/health/devices/fda_510k/{key}`
- [openFDA premarket approvals (PMA)](#listFdaPma): `GET /v1/health/devices/fda_pma`
- [One record of: openFDA premarket approvals (PMA)](#getFdaPma): `GET /v1/health/devices/fda_pma/{key}`
- [openFDA device classification](#listFdaClassification): `GET /v1/health/devices/fda_classification`
- [One record of: openFDA device classification](#getFdaClassification): `GET /v1/health/devices/fda_classification/{key}`
- [openFDA unique device identifiers (UDI)](#listFdaUdi): `GET /v1/health/devices/fda_udi`
- [One record of: openFDA unique device identifiers (UDI)](#getFdaUdi): `GET /v1/health/devices/fda_udi/{key}`
- [openFDA device registration and listing](#listFdaRegistrationlisting): `GET /v1/health/devices/fda_registrationlisting`
- [One record of: openFDA device registration and listing](#getFdaRegistrationlisting): `GET /v1/health/devices/fda_registrationlisting/{key}`
- [openFDA COVID-19 serology tests](#listFdaCovid19serology): `GET /v1/health/devices/fda_covid19serology`
- [One record of: openFDA COVID-19 serology tests](#getFdaCovid19serology): `GET /v1/health/devices/fda_covid19serology/{key}`
- [openFDA device recalls](#listFdaRecall): `GET /v1/health/devices/fda_recall`
- [One record of: openFDA device recalls](#getFdaRecall): `GET /v1/health/devices/fda_recall/{key}`
- [openFDA device enforcement reports](#listFdaDeviceEnforcement): `GET /v1/health/devices/fda_device_enforcement`
- [One record of: openFDA device enforcement reports](#getFdaDeviceEnforcement): `GET /v1/health/devices/fda_device_enforcement/{key}`

## FDA 510(k) summary documents (extracted text) {#listFdaSummaries}

`GET /v1/health/devices/fda_510k_summary`

The text of 510(k) summary documents, one row per clearance, as the worker extracted it from the PDF. Only clearances whose document produced text are listed. Ordered by `(updated_at, k_number)` ascending; `updated_at` moves only when the text changes, so `updated_since` plus the cursor is a change feed. `k_number` matches the start of the number. `content` is left out unless `include=content`, and the page is then capped at 25 rows (a single summary can be two million characters). `meta.status` is `backfilling` while the first fill has clearances left; `meta.run` says how many. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `k_number` | query | no | string, pattern `^[A-Za-z0-9]{1,9}$` | A prefix of the clearance number: 1-9 letters or digits, upper-cased (`K23`, `DEN25`). |
| `decision_date_from` | query | no | string, date | YYYY-MM-DD, inclusive, on the FDA decision date. |
| `decision_date_to` | query | no | string, date | YYYY-MM-DD, inclusive. Not before `decision_date_from`. |
| `product_code` | query | no | string, pattern `^[A-Za-z0-9]{1,10}$` | Exact FDA product code, upper-cased. |
| `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 | `content` | `content` adds the extracted text (page cap 25). |
| `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-25 with `include=content` (the default then is 25). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_510k_summary?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_fda_summary`](https://docs.aggre.org/api/schemas.md#health_fda_summary).

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

## One 510(k) summary, with its text {#getFdaSummary}

`GET /v1/health/devices/fda_510k_summary/{k_number}`

The row with its `content`. Takes no query parameters. 404 for a clearance with no extracted text (the document has not been read yet, is not on the publisher's site, or has no text layer): the other states are the worker's bookkeeping and are not served. 400 for a number that is not letters then six digits. 503 `terms_unread` until a person has read the publisher's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `k_number` | path | yes | string, pattern `^[A-Za-z]+[0-9]{6}$` | A 510(k) clearance number: letters then six digits (`K232060`, `DEN250040`); lower case is accepted. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_510k_summary/<k_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_fda_summary`](https://docs.aggre.org/api/schemas.md#health_fda_summary).

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

## openFDA drug labels (prescribing information) {#listFdaLabel}

`GET /v1/health/drugs/fda_label`

Records of the openFDA endpoint `drug/label` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_label?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA drug labels (prescribing information) {#getFdaLabel}

`GET /v1/health/drugs/fda_label/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_label/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA National Drug Code directory {#listFdaNdc}

`GET /v1/health/drugs/fda_ndc`

Records of the openFDA endpoint `drug/ndc` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_ndc?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA National Drug Code directory {#getFdaNdc}

`GET /v1/health/drugs/fda_ndc/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_ndc/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA Drugs@FDA approvals {#listFdaDrugsfda}

`GET /v1/health/drugs/fda_drugsfda`

Records of the openFDA endpoint `drug/drugsfda` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_drugsfda?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA Drugs@FDA approvals {#getFdaDrugsfda}

`GET /v1/health/drugs/fda_drugsfda/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_drugsfda/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA Orange Book {#listFdaOrangebook}

`GET /v1/health/drugs/fda_orangebook`

Records of the openFDA endpoint `drug/orangebook` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_orangebook?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA Orange Book {#getFdaOrangebook}

`GET /v1/health/drugs/fda_orangebook/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_orangebook/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA drug shortages {#listFdaShortages}

`GET /v1/health/drugs/fda_shortages`

Records of the openFDA endpoint `drug/shortages` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_shortages?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA drug shortages {#getFdaShortages}

`GET /v1/health/drugs/fda_shortages/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_shortages/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA NDC SPL data elements (NSDE) {#listFdaNsde}

`GET /v1/health/drugs/fda_nsde`

Records of the openFDA endpoint `other/nsde` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_nsde?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA NDC SPL data elements (NSDE) {#getFdaNsde}

`GET /v1/health/drugs/fda_nsde/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_nsde/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA UNII substance identifiers {#listFdaUnii}

`GET /v1/health/drugs/fda_unii`

Records of the openFDA endpoint `other/unii` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_unii?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA UNII substance identifiers {#getFdaUnii}

`GET /v1/health/drugs/fda_unii/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_unii/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA substance data {#listFdaSubstance}

`GET /v1/health/drugs/fda_substance`

Records of the openFDA endpoint `other/substance` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_substance?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA substance data {#getFdaSubstance}

`GET /v1/health/drugs/fda_substance/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_substance/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA historical documents {#listFdaHistoricaldocument}

`GET /v1/health/drugs/fda_historicaldocument`

Records of the openFDA endpoint `other/historicaldocument` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_historicaldocument?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA historical documents {#getFdaHistoricaldocument}

`GET /v1/health/drugs/fda_historicaldocument/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_historicaldocument/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA drug enforcement reports (recalls) {#listFdaEnforcement}

`GET /v1/health/drugs/fda_enforcement`

Records of the openFDA endpoint `drug/enforcement` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_enforcement?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA drug enforcement reports (recalls) {#getFdaEnforcement}

`GET /v1/health/drugs/fda_enforcement/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_enforcement/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA complete response letters {#listFdaCrl}

`GET /v1/health/drugs/fda_crl`

Records of the openFDA endpoint `transparency/crl` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_crl?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA complete response letters {#getFdaCrl}

`GET /v1/health/drugs/fda_crl/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/drugs/fda_crl/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA 510(k) clearances {#listFda510k}

`GET /v1/health/devices/fda_510k`

Records of the openFDA endpoint `device/510k` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_510k?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA 510(k) clearances {#getFda510k}

`GET /v1/health/devices/fda_510k/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_510k/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA premarket approvals (PMA) {#listFdaPma}

`GET /v1/health/devices/fda_pma`

Records of the openFDA endpoint `device/pma` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_pma?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA premarket approvals (PMA) {#getFdaPma}

`GET /v1/health/devices/fda_pma/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one, such as `P140004/S092` or `P140004/`) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_pma/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA device classification {#listFdaClassification}

`GET /v1/health/devices/fda_classification`

Records of the openFDA endpoint `device/classification` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_classification?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA device classification {#getFdaClassification}

`GET /v1/health/devices/fda_classification/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_classification/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA unique device identifiers (UDI) {#listFdaUdi}

`GET /v1/health/devices/fda_udi`

Records of the openFDA endpoint `device/udi` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_udi?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA unique device identifiers (UDI) {#getFdaUdi}

`GET /v1/health/devices/fda_udi/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_udi/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA device registration and listing {#listFdaRegistrationlisting}

`GET /v1/health/devices/fda_registrationlisting`

Records of the openFDA endpoint `device/registrationlisting` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_registrationlisting?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA device registration and listing {#getFdaRegistrationlisting}

`GET /v1/health/devices/fda_registrationlisting/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_registrationlisting/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA COVID-19 serology tests {#listFdaCovid19serology}

`GET /v1/health/devices/fda_covid19serology`

Records of the openFDA endpoint `device/covid19serology` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_covid19serology?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA COVID-19 serology tests {#getFdaCovid19serology}

`GET /v1/health/devices/fda_covid19serology/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_covid19serology/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA device recalls {#listFdaRecall}

`GET /v1/health/devices/fda_recall`

Records of the openFDA endpoint `device/recall` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_recall?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA device recalls {#getFdaRecall}

`GET /v1/health/devices/fda_recall/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_recall/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## openFDA device enforcement reports {#listFdaDeviceEnforcement}

`GET /v1/health/devices/fda_device_enforcement`

Records of the openFDA endpoint `device/enforcement` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. |
| `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 (a page can be shorter, see above). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_device_enforcement?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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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

## One record of: openFDA device enforcement reports {#getFdaDeviceEnforcement}

`GET /v1/health/devices/fda_device_enforcement/{key}`

One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/health/devices/fda_device_enforcement/<key>" \
  -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_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record).

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