# Product Recall & Safety API — search and track product recalls from the US FDA (food, drug, device) and the EU Safety Gate (RAPEX): search, detail, by-company, latest and stats

> Search FDA recalls by keyword, category, classification, status, company, and date range with skip/limit pagination. Pass category=all (default) to span food+drug+device.
> ReefAPI engine `recall` · 10 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/recall/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /recall/v1/search — 1 credit
Search FDA recalls by keyword, category, classification, status, company, and date range with skip/limit pagination. Pass category=all (default) to span food+drug+device.

**Parameters:**
- `query` (string, optional) — Free-text product/keyword search over the recall's product description and reason . e.g. 'peanut butter', 'listeria', 'airbag'. Combine with category/classification/date.
- `category` (enum, optional, default "all") — FDA recall category. food / drug / device, or 'all' to search every category at once. (CPSC consumer-product & NHTSA vehicle recalls are out of scope — see docs; vehicle recalls live in the `vehicle` API.) [one of: food, drug, device, all]
- `classification` (enum, optional) — FDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier. [one of: Class I, Class II, Class III]
- `status` (enum, optional) — Recall lifecycle status. Case-insensitive; unknown values are ignored rather than rejected. [one of: Ongoing, Completed, Terminated, Pending]
- `company` (string, optional) — Optional recalling-firm filter to narrow a search.
- `date_from` (string, optional) — Filter by recall report_date from (on or after). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
- `date_to` (string, optional) — Filter by recall report_date to (on or before). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
- `sort` (enum, optional, default "report_date:desc") — Result ordering by date field. [one of: report_date:desc, report_date:asc, recall_initiation_date:desc, recall_initiation_date:asc]
- `limit` (integer, optional, default 20) — Results per page (1-100, default 20). Larger values are clamped.
- `skip` (integer, optional, default 0) — Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.
- `include_severity` (boolean, optional, default true) — Include the 0-100 severity_score on each recall (default true).

**Returns:** recalls[] (normalized FDA enforcement records w/ severity_score), total, skip, limit, has_more, next_skip, categories_searched[]

**Example request body:**
```json
{
  "query": "listeria",
  "category": "food",
  "limit": 3
}
```

### POST /recall/v1/recall_detail — 1 credit
Full detail for one recall by its FDA recall_number (category auto-detected from prefix).

**Parameters:**
- `recall_number` (string, required) — The FDA recall_number (e.g. F-0001-2018, D-1234-2025, Z-1234-2025) from a search result. Category is auto-detected from the prefix (F=food, D=drug, Z=device) but pass category to be explicit.
- `category` (enum, optional) — FDA recall category. food / drug / device, or 'all' to search every category at once. (CPSC consumer-product & NHTSA vehicle recalls are out of scope — see docs; vehicle recalls live in the `vehicle` API.) [one of: food, drug, device, all]

**Returns:** recall{} — the full normalized recall record

**Example request body:**
```json
{
  "recall_number": "F-1397-2012"
}
```

### POST /recall/v1/by_company — 1 credit
All recalls for a recalling firm / manufacturer, newest first, paginated.

**Parameters:**
- `company` (string, required) — Recalling firm / company name (matched against openFDA recalling_firm). Case-insensitive, partial words allowed.
- `category` (enum, optional, default "all") — FDA recall category. food / drug / device, or 'all' to search every category at once. (CPSC consumer-product & NHTSA vehicle recalls are out of scope — see docs; vehicle recalls live in the `vehicle` API.) [one of: food, drug, device, all]
- `classification` (enum, optional) — FDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier. [one of: Class I, Class II, Class III]
- `status` (enum, optional) — Recall lifecycle status. Case-insensitive; unknown values are ignored rather than rejected. [one of: Ongoing, Completed, Terminated, Pending]
- `date_from` (string, optional) — Filter by recall report_date from (on or after). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
- `date_to` (string, optional) — Filter by recall report_date to (on or before). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
- `limit` (integer, optional, default 20) — Results per page (1-100, default 20). Larger values are clamped.
- `skip` (integer, optional, default 0) — Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.
- `include_severity` (boolean, optional, default true) — Include the 0-100 severity_score on each recall (default true).

**Returns:** recalls[] for the firm, company, total, has_more, next_skip

**Example request body:**
```json
{
  "company": "Pfizer",
  "category": "drug",
  "limit": 3
}
```

### POST /recall/v1/latest — 1 credit
Most recent recalls across all categories (or one), within the last N days.

**Parameters:**
- `category` (enum, optional, default "all") — FDA recall category. food / drug / device, or 'all' to search every category at once. (CPSC consumer-product & NHTSA vehicle recalls are out of scope — see docs; vehicle recalls live in the `vehicle` API.) [one of: food, drug, device, all]
- `classification` (enum, optional) — FDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier. [one of: Class I, Class II, Class III]
- `days` (integer, optional, default 90) — `latest` window: recalls reported in the last N days (default 90).
- `limit` (integer, optional, default 20) — Results per page (1-100, default 20). Larger values are clamped.
- `skip` (integer, optional, default 0) — Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.
- `include_severity` (boolean, optional, default true) — Include the 0-100 severity_score on each recall (default true).

**Returns:** recalls[] (newest first), window_days, categories_searched[], total, has_more

**Example request body:**
```json
{
  "days": 120,
  "limit": 3
}
```

### POST /recall/v1/batch — 1 credit
Run multiple keyword searches in one call (compliance-watch over a product list).

**Parameters:**
- `queries` (array, required) — Up to 20 keyword queries; each is searched and returned with its own results. A JSON array or a comma/newline-separated string.
- `category` (enum, optional, default "all") — FDA recall category. food / drug / device, or 'all' to search every category at once. (CPSC consumer-product & NHTSA vehicle recalls are out of scope — see docs; vehicle recalls live in the `vehicle` API.) [one of: food, drug, device, all]
- `classification` (enum, optional) — FDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier. [one of: Class I, Class II, Class III]
- `limit` (integer, optional, default 20) — Results per page (1-100, default 20). Larger values are clamped.

**Returns:** results[] — one {query, count, recalls[]} block per query

**Example request body:**
```json
{
  "queries": [
    "listeria",
    "salmonella"
  ],
  "category": "food",
  "limit": 2
}
```

### POST /recall/v1/stats — 1 credit
Aggregate recall counts grouped by a field (classification/status/firm/state/type).

**Parameters:**
- `category` (enum, optional, default "all") — FDA recall category. food / drug / device, or 'all' to search every category at once. (CPSC consumer-product & NHTSA vehicle recalls are out of scope — see docs; vehicle recalls live in the `vehicle` API.) [one of: food, drug, device, all]
- `field` (enum, optional, default "classification") — Aggregate recall counts grouped by this field (openFDA count). Returns term→count buckets. [one of: classification, status, recalling_firm, state, product_type]
- `query` (string, optional) — Free-text product/keyword search over the recall's product description and reason . e.g. 'peanut butter', 'listeria', 'airbag'. Combine with category/classification/date.
- `date_from` (string, optional) — Filter by recall report_date from (on or after). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
- `date_to` (string, optional) — Filter by recall report_date to (on or before). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.

**Returns:** buckets[] (term, count), field, category, total_terms

**Example request body:**
```json
{
  "category": "food",
  "field": "classification"
}
```

### POST /recall/v1/categories — 1 credit
The recall taxonomy: FDA categories + EU Safety Gate product-category & risk-type enums + EU country list (reference data for filters).

**Parameters:** none

**Returns:** fda_categories[], fda_classifications[], eu_product_categories[], eu_risk_types[], eu_countries_count

### POST /recall/v1/eu_recall — 1 credit
One EU Safety Gate (RAPEX) recall/alert by notification id — product, risk, measure, traceability, reacting countries.

**Parameters:**
- `id` (integer, required) — EU Safety Gate notification id (from a safety-gate-alerts URL).
- `language` (string, optional, default "en") — Preferred language for the EU notification text (e.g. en, de, fr).

**Returns:** recall{} — normalized EU notification (source=EU Safety Gate)

**Example request body:**
```json
{
  "id": 10000308
}
```

### POST /recall/v1/eu_recalls — 1 credit
Search/list EU Safety Gate alerts (the EU analogue of `search`): pages over recent weekly reports (open-data XML) and filters by query, product category, country and risk type, with skip/limit pagination. Each alert carries product, barcode, brand, risk, measures, notifying country and country of origin.

**Parameters:**
- `query` (string, optional) — Free-text filter over the EU alert's product name/description, brand, category and risk description (case-insensitive substring).
- `category` (string, optional) — EU Safety Gate product category to filter on (e.g. Toys, Motor vehicles, Electrical appliances). See the `categories` action for the full enum. Substring match.
- `country` (string, optional) — Filter to alerts whose notifying country OR country of origin matches (e.g. Germany, China). Substring, case-insensitive.
- `risk_type` (string, optional) — Filter by risk type / hazard (e.g. Chemical, Choking, Suffocation, Injuries, Electric shock). Substring over the alert's risk types.
- `weeks` (integer, optional, default 12) — How many of the most-recent weekly reports to scan (1-12; each carries ~80-100 alerts). Larger = more coverage + more upstream fetches.
- `limit` (integer, optional, default 20) — Results per page (1-100, default 20). Larger values are clamped.
- `skip` (integer, optional, default 0) — Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.

**Returns:** recalls[] (normalized EU alerts), total, reports_scanned, weeks_window, newest_report{}, filters{}, skip, limit, has_more, next_skip

**Example request body:**
```json
{
  "category": "Toys",
  "weeks": 2,
  "limit": 3
}
```

### POST /recall/v1/eu_latest — 1 credit
The newest EU Safety Gate weekly report fully expanded into its ~80-100 product alerts (newest-published recalls across the EU/EEA).

**Parameters:**
- `limit` (integer, optional, default 20) — Results per page (1-100, default 20). Larger values are clamped.

**Returns:** report{reference,week,year,publication_date}, recalls[], total_in_report

**Example request body:**
```json
{
  "limit": 3
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=recall
- Human docs page: https://reefapi.com/docs/recall
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
