Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the Product Recall & Safety API page →
Utilities & AI

Product Recall & Safety API

The Product Recall API returns FDA product-safety recalls as clean JSON.

10 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

The primary search endpoint returns normalized enforcement records with a severity score, and you can pull a recall_detail, recalls by company, the latest recalls, stats and categories, and batch. It is built for compliance, marketplace safety and consumer apps that need recall data without parsing raw FDA feeds. One ReefAPI key, one shared credit pool, the standard envelope.

Reference

Recall number prefixes, hazard classes and the severity score

The recall_number prefix, not a category field, is what tells you which FDA registry a row came from, and recall_detail auto-detects the category from it. The hazard class and the derived severity_score are two different things, and the score is ours rather than the FDA's. Everything below was read off live responses in August 2026.

ValueWhat it meansMeasured
H-…Food and cosmetics recall. This is the prefix most current food recalls actually carry, not FH-1034-2026, Albertsons peanut butter bar, Class II; 15 of 50 rows in a 30-day latest sweep
F-…Also food, from the older enforcement numbering. recall_detail still resolves it to category foodF-1397-2012 returned meta.category food without passing category
D-…Human and animal drug recallD-0590-2025, PFIZER INC, Class II, Ongoing
Z-…Medical device recall17 of 50 rows in the same 30-day latest sweep
Class I / II / IIIFDA hazard tier, I being the most seriousfood stats: 12,867 Class I, 14,704 Class II, 1,745 Class III
Not Yet ClassifiedA fourth classification value the parameter enum does not list, used while the FDA has not tiered the recall yet2 of 50 rows in the 30-day sweep; 1 row in the all-time food classification stats
severity_scoreA derived 0-100 number built from hazard class plus lifecycle status. It is not an FDA fieldClass I ongoing 80-100, Class I terminated 70, Class II 55-75, Class III 45, Not Yet Classified 50-60
Date fieldsPlain YYYYMMDD strings with no separators, and null when the event has not happenedreport_date 20260610, termination_date 20260702 on a terminated recall and null on an ongoing one

status accepts Ongoing, Completed, Terminated and Pending and is declared on_invalid=ignore, so a typo silently returns unfiltered results instead of an error. classification and category are on_invalid=reject and fail loudly instead.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/recall/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "query": "listeria",
    "category": "food",
    "limit": 3
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "recall",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 1143.9,
    "record_count": 3,
    "bytes": 4182,
    "cache_hit": false,
    "sources": "openFDA-RES + EU-Safety-Gate",
    "categories_searched": [
      "food"
    ],
    "total": 7469,
    "skip": 0,
    "limit": 3,
    "has_more": true,
    "next_skip": 3
  },
  "data": {
    "recalls": [
      {
        "source": "openFDA",
        "category": "food",
        "recall_number": "H-[redacted-phone]",
        "event_id": "98993",
        "status": "Ongoing",
        "classification": "Class I",
        "severity_score": 80,
        "recalling_firm": "HH FRESH TRADING CORP",
        "product_description": "HH Fresh Trading Corp. (branded) ENOKI MUSHROOM; Premium Quality; Net WT/ Poids Net 150g(5.29oz) Distributed by HH Fresh Trading Exported by JIA YANG INTERNATIONAL ENTERPRISES CO., LTD. Produced by Green Farm (Taiwan)  UPC: [redacted-phone]",
        "product_quantity": "120 cases",
        "reason_for_recall": "Imported Enoki Mushrooms tested positive for Listeria Monocytogenes.",
        "code_info": "No lot codes",
        "product_type": "Food",
        "voluntary_mandated": "Voluntary: Firm initiated",
        "initial_firm_notification": "Telephone",
        "distribution_pattern": "Product was distributed to a single customer located in Texas. Product was further distributed as samples were collected in Florida.",
        "city": "Los Angeles",
        "state": "CA",
        "country": "United States",
        "recall_initiation_date": "20260511",
        "center_classification_date": "20260610",
        "report_date": "20260617",
        "termination_date": null,
        "more_code_info": null,
        "brand_name": null,
        "generic_name": null,
        "manufacturer_name": null,
        "product_ndc": null,
        "substance_name": null,
        "device_name": null,
        "medical_specialty_description": null,
        "openfda": null
      },
      {
        "source": "openFDA",
        "category": "food",
        "recall_number": "H-[redacted-phone]",
        "event_id": "99001",
        "status": "Ongoing",
        "classification": "Class I",
        "severity_score": 80,
        "recalling_firm": "IQ PRODUCE, LLC",
        "product_description": "Enoki Mushroom, Net Weight 150g; Product of Korea; Distributed by IQ Produce UPC: [redacted-phone]",
        "product_quantity": "319 units",
        "reason_for_recall": "Imported Enoki Mushrooms samples collected by Florida Department of Health tested positive for Listeria Monocytogenes.",
        "code_info": "Lot UI775",
        "product_type": "Food",
        "voluntary_mandated": "Voluntary: Firm initiated",
        "initial_firm_notification": "Two or more of the following: Email, Fax, Letter, Press Release, Telephone, Visit",
        "distribution_pattern": "Product was distributed to 3 California customers.",
        "city": "Vernon",
        "state": "CA",
        "country": "United States",
        "recall_initiation_date": "20260514",
        "center_classification_date": "20260602",
        "report_date": "20260610",
        "termination_date": null,
        "more_code_info": "",
        "brand_name": null,
        "generic_name": null,
        "manufacturer_name": null,
        "product_ndc": null,
        "substance_name": null,
        "device_name": null,
        "medical_specialty_description": null,
        "openfda": null
      },
      {
        "source": "openFDA",
        "category": "food",
        "recall_number": "H-[redacted-phone]",
        "event_id": "98725",
        "status": "Ongoing",
        "classification": "Class I",
        "severity_score": 90,
        "recalling_firm": "HEMU TRADING INC",
        "product_description": "Black label with blue lettering. FOOD Korean Food, ENOKI MUSHROOM, 150g clear plastic package; Product of Korea, Keep Refrigerated. Distributed by Hemu Trading Inc. UPC: [redacted-phone]",
        "product_quantity": "1056 cases (34 packs/case)",
        "reason_for_recall": "product tested positive for Listeria Monocytogenes.",
        "code_info": "Lot code:215",
        "product_type": "Food",
        "voluntary_mandated": "Voluntary: Firm initiated",
        "initial_firm_notification": "Two or more of the following: Email, Fax, Letter, Press Release, Telephone, Visit",
        "distribution_pattern": "5 direct account consignees located in CA, FL and MD.",
        "city": "Los Angeles",
        "state": "CA",
        "country": "United States",
        "recall_initiation_date": "20260402",
        "center_classification_date": "20260430",
        "report_date": "20260506",
        "termination_date": null,
        "more_code_info": "",
        "brand_name": null,
        "generic_name": null,
        "manufacturer_name": null,
        "product_ndc": null,
        "substance_name": null,
        "device_name": null,
        "medical_specialty_description": null,
        "openfda": null
      }
    ],
    "categories_searched": [
      "food"
    ],
    "total": 7469,
    "skip": 0,
    "limit": 3,
    "has_more": true,
    "next_skip": 3
  }
}
Actions

What the Product Recall & Safety API does

ActionDescriptionConcrete use caseKey params
searchSearch FDA recalls by keyword, category, classification, status, company, and date range with skip/limit pagination. Pass category=all (default) to span food+drug+device.Ops teams call search to search FDA recalls by keyword, category, classification, status, company, and date range with….query, category, classification, status, company, ...
recall_detailFull detail for one recall by its FDA recall_number (category auto-detected from prefix).Developer tools call recall_detail to get full detail for one recall by its FDA recall_number (category auto-detected from prefix)..recall_number, category
by_companyAll recalls for a recalling firm / manufacturer, newest first, paginated.Validation workflows call by_company to get all recalls for a recalling firm / manufacturer, newest first, paginated..company, category, classification, status, date_from, ...
latestMost recent recalls across all categories (or one), within the last N days.Data-quality teams call latest to get most recent recalls across all categories (or one), within the last N days..category, classification, days, limit, skip, ...
batchRun multiple keyword searches in one call (compliance-watch over a product list).Ops teams call batch to get run multiple keyword searches in one call (compliance-watch over a product list)..queries, category, classification, limit
statsAggregate recall counts grouped by a field (classification/status/firm/state/type).Developer tools call stats to get aggregate recall counts grouped by a field (classification/status/firm/state/type)..category, field, query, date_from, date_to
categoriesThe recall taxonomy: FDA categories + EU Safety Gate product-category & risk-type enums + EU country list (reference data for filters).Validation workflows call categories to get the recall taxonomy.none
eu_recallOne EU Safety Gate (RAPEX) recall/alert by notification id — product, risk, measure, traceability, reacting countries.Data-quality teams call eu_recall to get one EU Safety Gate (RAPEX) recall/alert by notification id.id, language
eu_recallsSearch/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.Ops teams call eu_recalls to get search/list EU Safety Gate alerts (the EU analogue of `search`).query, category, country, risk_type, weeks, ...
eu_latestThe newest EU Safety Gate weekly report fully expanded into its ~80-100 product alerts (newest-published recalls across the EU/EEA).Developer tools call eu_latest to get the newest EU Safety Gate weekly report fully expanded into its ~80-100 product alerts (newes….limit
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/recall/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"listeria","category":"food","limit":3}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.recall.search with {"query":"listeria","category":"food","limit":3}.
Use cases

Who uses this API and why

  • Marketplaces call by_company to flag products from a brand with active recalls.
  • Compliance teams monitor latest recalls for their categories.
  • Consumer apps use search and recall_detail to warn users.
FAQ

Questions developers ask before integrating

Why does my food recall number start with H when the docs say F means food?

Both prefixes are food. F belongs to the older enforcement numbering and H is what current food recalls carry: in a 30-day latest sweep all 15 food rows were H-something, for example H-1034-2026 from Albertsons. You do not have to work it out yourself. recall_detail auto-detects the category from the prefix, and passing only recall_number H-1034-2026 came back with meta.category food.

Does this cover vehicle, CPSC or EU recalls?

Not in the search results. Every row measured across search, latest and by_company carried source openFDA, covering the FDA food, drug and device registries only. The categories action does return EU Safety Gate reference vocabulary, 34 product-category keys, 22 risk types and a 251-entry country list, but no EU rows came back from the data actions. NHTSA vehicle recalls are a separate engine.

Is severity_score an FDA number?

No. The FDA publishes a hazard class, not a score. severity_score is derived from that class plus the recall's lifecycle status, which is why one class spans a range: ongoing Class I recalls measured 80, 90 and 100 while a terminated Class I, F-1397-2012, scored 70. Class II ran 55 to 75 and Class III 45. Set include_severity to false if you want the record without it.

Why did stats ignore my category=all?

stats aggregates one registry at a time. A call with field classification and category all came back with meta.category food and food-only buckets. To get cross-category totals, run stats once per category and add them up. The same call with category drug returned its own buckets: 14,801 Terminated, 2,662 Ongoing and 436 Completed.

Which fields come back null on a normal record?

The drug and device specific fields are null on food rows and the other way round. On measured food records brand_name, generic_name, manufacturer_name, product_ndc, substance_name, device_name and openfda were all null, while product_description, reason_for_recall, recalling_firm, city, state and the dates were populated. termination_date is null for anything still Ongoing. Check the field you need, not whether a record came back.

How do I page past the first 20 results?

Every list response carries total, has_more and next_skip, and you feed next_skip back in as skip. limit tops out at 100 per page and the underlying ceiling is skip plus limit at most 25,000, so roughly 25,000 records per filter combination. A search for peanut butter in food reported total 680 with limit 3 and next_skip 3.

What does latest with category=all actually return?

It fans out across all three registries and merges them, so a limit of 50 is not 50 rows from one place. A measured 30-day window returned 16 food, 17 drug and 17 device rows, with meta.categories_searched listing all three and total 328. Ordering is newest report_date first, and the window is set by days, which defaults to 90 and caps at 3,650.

Can I watch a list of products in one request?

Yes. batch takes up to 20 keyword queries and returns a separate {query, count, recalls[]} block for each, which is the compliance-watch shape. If you already know the firm, by_company is more precise: it matches the FDA recalling_firm field case-insensitively on partial words, which is why a Pfizer query returned rows filed under both PFIZER INC and Pfizer, 155 in total in the drug registry.

What is the Product Recall & Safety API?

Product Recall & Safety API is a ReefAPI endpoint group for product recall & safety It returns live JSON through POST requests under /recall/v1.

Is the Product Recall & Safety API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Product Recall & Safety calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Product Recall & Safety login or account?

No login to Product Recall & Safety is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Product Recall & Safety data?

The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Product Recall & Safety API use?

Product Recall & Safety actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Product Recall & Safety from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call recall actions with the same key, credit pool and JSON envelope used by normal REST requests.

docs / recall

Product Recall & Safety

Product Recall & Safety

base /recall/v110 endpoints
post/recall/v1/recall_detail1 credit

Full detail for one recall by its FDA recall_number (category auto-detected from prefix).

ParameterAllowed / rangeDescription
recall_numberrequiredThe 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.
categoryoptionalfood · drug · device · allFDA 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.)
Try in playground →
post/recall/v1/by_company1 credit

All recalls for a recalling firm / manufacturer, newest first, paginated.

ParameterAllowed / rangeDescription
companyrequiredRecalling firm / company name (matched against openFDA recalling_firm). Case-insensitive, partial words allowed.
category = alloptionalfood · drug · device · allFDA 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.)
classificationoptionalClass I · Class II · Class IIIFDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier.
statusoptionalOngoing · Completed · Terminated · PendingRecall lifecycle status. Case-insensitive; unknown values are ignored rather than rejected.
date_fromoptionalFilter by recall report_date from (on or after). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
date_tooptionalFilter by recall report_date to (on or before). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
limit = 20optional1–100Results per page (1-100, default 20). Larger values are clamped.
skip = 0optional0–25000Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.
include_severity = trueoptionalInclude the 0-100 severity_score on each recall (default true).
Try in playground →
post/recall/v1/latest1 credit

Most recent recalls across all categories (or one), within the last N days.

ParameterAllowed / rangeDescription
category = alloptionalfood · drug · device · allFDA 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.)
classificationoptionalClass I · Class II · Class IIIFDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier.
days = 90optional1–3650`latest` window: recalls reported in the last N days (default 90).
limit = 20optional1–100Results per page (1-100, default 20). Larger values are clamped.
skip = 0optional0–25000Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.
include_severity = trueoptionalInclude the 0-100 severity_score on each recall (default true).
Try in playground →
post/recall/v1/batch1 credit

Run multiple keyword searches in one call (compliance-watch over a product list).

ParameterAllowed / rangeDescription
queriesrequiredUp to 20 keyword queries; each is searched and returned with its own results. A JSON array or a comma/newline-separated string.
category = alloptionalfood · drug · device · allFDA 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.)
classificationoptionalClass I · Class II · Class IIIFDA hazard classification. Case-insensitive. Filters to recalls of that seriousness tier.
limit = 20optional1–100Results per page (1-100, default 20). Larger values are clamped.
Try in playground →
post/recall/v1/stats1 credit

Aggregate recall counts grouped by a field (classification/status/firm/state/type).

ParameterAllowed / rangeDescription
category = alloptionalfood · drug · device · allFDA 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.)
field = classificationoptionalclassification · status · recalling_firm · state · product_typeAggregate recall counts grouped by this field (openFDA count). Returns term→count buckets.
queryoptionalFree-text product/keyword search over the recall's product description and reason . e.g. 'peanut butter', 'listeria', 'airbag'. Combine with category/classification/date.
date_fromoptionalFilter by recall report_date from (on or after). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
date_tooptionalFilter by recall report_date to (on or before). ISO YYYY-MM-DD (or YYYYMMDD). Pair date_from + date_to for a range.
Try in playground →
post/recall/v1/categories1 credit

The recall taxonomy: FDA categories + EU Safety Gate product-category & risk-type enums + EU country list (reference data for filters).

Try in playground →
post/recall/v1/eu_recall1 credit

One EU Safety Gate (RAPEX) recall/alert by notification id — product, risk, measure, traceability, reacting countries.

ParameterAllowed / rangeDescription
idrequiredEU Safety Gate notification id (from a safety-gate-alerts URL).
language = enoptionalPreferred language for the EU notification text (e.g. en, de, fr).
Try in playground →
post/recall/v1/eu_recalls1 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.

ParameterAllowed / rangeDescription
queryoptionalFree-text filter over the EU alert's product name/description, brand, category and risk description (case-insensitive substring).
categoryoptionalEU Safety Gate product category to filter on (e.g. Toys, Motor vehicles, Electrical appliances). See the `categories` action for the full enum. Substring match.
countryoptionalFilter to alerts whose notifying country OR country of origin matches (e.g. Germany, China). Substring, case-insensitive.
risk_typeoptionalFilter by risk type / hazard (e.g. Chemical, Choking, Suffocation, Injuries, Electric shock). Substring over the alert's risk types.
weeks = 12optionalHow many of the most-recent weekly reports to scan (1-12; each carries ~80-100 alerts). Larger = more coverage + more upstream fetches.
limit = 20optional1–100Results per page (1-100, default 20). Larger values are clamped.
skip = 0optional0–25000Pagination offset (skip N results). Page forward with meta.next_skip. openFDA ceiling: skip+limit <= 25000.
Try in playground →
post/recall/v1/eu_latest1 credit

The newest EU Safety Gate weekly report fully expanded into its ~80-100 product alerts (newest-published recalls across the EU/EEA).

ParameterAllowed / rangeDescription
limit = 20optional1–100Results per page (1-100, default 20). Larger values are clamped.
Try in playground →