FDA Recalls & Enforcement Monitor: openFDA Reports
Pricing
from $0.07 / 1,000 recall records
FDA Recalls & Enforcement Monitor: openFDA Reports
Track FDA food, drug and medical device recalls from the official openFDA enforcement reports. Filter by class, status, firm, product, reason and state; get all four dates and see which recalls are new or updated since your last run.
Pricing
from $0.07 / 1,000 recall records
Rating
0.0
(0)
Developer
Cliqto Media
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Share
FDA Recalls & Enforcement Monitor searches FDA recalls of food, drugs and medical devices in the official FDA Enforcement Reports, through the openFDA API. Filter by recall class, status, dates, firm, product, reason and firm state. You get one clean row per recalled product, with the four FDA dates kept apart, the recall number, the firm, the reason and a link to the record in openFDA.
It is made for food and pharma quality teams, compliance and supplier monitoring, retailers, journalists and researchers. Save a monitor key and the next run shows only new and updated recalls. No login and no API key are needed. The form example (20 Class I food recalls from the last 30 days) finishes in a few seconds and costs $0.004.

Contents
- What it does
- Quick start
- Use cases
- Input
- Output
- Pricing
- Monitoring on a schedule
- API and integrations
- Limits
- Troubleshooting
- FAQ
- Data source and licence
- Related Actors
- Support
What it does
The Actor reads the public openFDA enforcement endpoints live: food (also cosmetics and dietary supplements), drug and device. These are the records of the FDA weekly Enforcement Report: every recall that FDA has classified or is about to classify.
- One request per category. Each category you pick is one search, newest records first.
maxResultsapplies to each category. - Four dates, never mixed.
recallInitiationDate(the firm started the recall),centerClassificationDate(FDA set the class),reportDate(FDA published it in the Enforcement Report) andterminationDate(FDA closed it). You choose which date your range uses. - Not yet classified recalls. The newest recalls appear before FDA gives them a class and a recall number. You can include or skip them. They get a stable
recallKeyanyway. - Monitoring. With a
monitorKey, the Actor saves the recalls it saw in your account. The next run marks each recallnew,updated(for example the status changed toTerminated) orunchanged, and by default writes only new and updated ones.
This is FDA data as published. It is not medical advice. Do not use it to decide whether to use, take or stop a product. Follow the instructions of FDA, the firm and your doctor or pharmacist.
Good fit
- Get a weekly list of new Class I food recalls for your quality or safety team.
- Check if a supplier, brand or competitor had FDA recalls, by firm name.
- Find recalls by reason:
Listeria,undeclared peanut,sterility,mislabeling. - Watch medical device or drug recalls of one firm state, such as
CAorNJ. - Feed FDA recall rows into a spreadsheet, a dashboard or an AI agent.
Not a fit
- Official consumer alerts or a guarantee that you see every recall in time. FDA publishes Enforcement Reports weekly, and a recall can appear later than the firm's press release.
- Full recall lifecycle tracking. The Actor sees only what the Enforcement Report says on the day of the run.
- Cosmetics or tobacco as separate categories, animal food recall press releases, and device recall details from the separate device recall database.
- A full copy of all FDA recalls since 2004. Use the openFDA downloads for that.
Quick start
- Open the Input tab. The form already has an example: food, Class I, last 30 days, 20 recalls.
- Click Start.
- Open the Recalls view in the Output tab. Check
recallNumber,recallingFirm,productDescription,reasonForRecallandreportDate. - Change the categories, classes or filters to your own. To get only changes next time, add a
monitorKeysuch asfood-class-1.
Expected result: up to 20 recall rows in a few seconds, newest first.
Use cases
| Buyer job | Input | Output | Key fields |
|---|---|---|---|
| Weekly food safety watch | categories: ["food"], classifications: ["I"], monitorKey, on a schedule | only new and updated Class I recalls | changeType, reasonForRecall, distributionPattern |
| Supplier check | firmNames, all categories, a 90-day range | that firm's recalls | recallingFirm, productDescription, status |
| Allergen or pathogen research | reasonQuery: "Listeria" or "undeclared peanut" | matching recalls | reasonForRecall, codeInfo, productQuantity |
| Medical device recall search | categories: ["device"], productQuery, firmStates | device recall rows | recallNumber, classification, centerClassificationDate |
| Drug recall list with NDCs | categories: ["drug"] | drug rows | drugBrandNames, drugGenericNames, drugProductNdcs |
| Closed recalls | dateField: "termination_date" | recalls FDA terminated in the range | terminationDate, status |
Input
All filters are optional and combine with AND. Values inside one list combine with OR.
| Field | Type | Default | Allowed values | What it does |
|---|---|---|---|---|
categories | array | ["food"] | food, drug, device | Which openFDA endpoints to search. food also has cosmetics and dietary supplements. |
classifications | array | all | I, II, III, unclassified | FDA recall class. Class I is the most serious. unclassified = not yet classified. Empty = all. |
statuses | array | all | Ongoing, Completed, Terminated | Recall status. Empty = all. |
lookbackDays | integer | 30 | 1–90 | Days back from dateTo. Ignored when dateFrom is set. |
dateField | string | report_date | report_date, recall_initiation_date, center_classification_date, termination_date | Which FDA date the range uses. |
dateFrom, dateTo | date | dateTo = today (UTC) | YYYY-MM-DD, from 2004 | Exact range, at most 90 days. Split longer periods into several runs. |
firmNames | array of strings | none | up to 10; 2–120 characters | Phrase in the recalling firm name. Whole Foods matches Whole Foods Market Group Inc. |
productQuery | string | none | 2–120 characters | Phrase in the product description, like ice cream or insulin pump. |
reasonQuery | string | none | 2–120 characters | Phrase in the reason for recall, like Listeria or undeclared milk. |
firmStates | array of strings | none | up to 20 two-letter codes | State of the recalling firm, like CA. It is not where the product was sold; see distributionPattern. |
maxResults | integer | 100 | 1–1000 | Maximum recalls per category, newest first. |
monitorKey | string | none | 1–40 letters, digits or dashes | Saves this run's recalls and compares the next run with them. One key per saved search. |
previousDatasetId | string | none | dataset ID | Compares with the dataset of an earlier run of this Actor. Use this or monitorKey, not both. |
onlyChanges | boolean | true | With a comparison, skip unchanged recalls. You do not pay for skipped recalls. | |
openFdaApiKey | string (secret) | none | your free openFDA key | Optional. Gives you your own openFDA quota. Never written to output or logs. |
Text filters search FDA's English text. Letters with accents are changed to plain Latin letters, and symbols such as ;, # or | are removed, because openFDA rejects them. A filter with no Latin letters or digits stops the run with INVALID_INPUT.
Input examples
Drug and device recalls of one firm, last 90 days:
{"categories": ["drug", "device"],"firmNames": ["Baxter"],"lookbackDays": 90,"maxResults": 200}
Weekly watch of Listeria recalls in food, only changes:
{"categories": ["food"],"reasonQuery": "Listeria","lookbackDays": 30,"maxResults": 300,"monitorKey": "food-listeria"}
Output
Each Dataset row is one recalled product (one FDA recall number). One recall event (eventId) can have several products. Use the Recalls view for the main fields and the Changes view for monitoring. The key-value store has a RUN_SUMMARY record with the run status and counts.
Output example
A real row from the form example (trimmed):
{"recallKey": "food:H-1395-2026","recallNumber": "H-1395-2026","eventId": "99874","category": "food","classification": "Class I","recallClass": "I","status": "Ongoing","recallingFirm": "WFM Purchasing, LP","productDescription": "Fromagerie Coop de Mean Cabricharme and Belgium Cabricharme ...","productQuantity": "21 Wheels","reasonForRecall": "Undeclared Egg Allergen","distributionPattern": "CA, AZ, NJ, MA, RI, CT, NY","recallInitiationDate": "2026-09-08","centerClassificationDate": "2026-09-22","reportDate": "2026-09-30","terminationDate": null,"city": "Austin","state": "TX","changeType": null,"sourceUrl": "https://api.fda.gov/food/enforcement.json?search=recall_number%3A%22H-1395-2026%22","provider": "openFDA (U.S. Food and Drug Administration)","sourceUpdatedAt": "2026-09-30","fetchedAt": "2026-10-12T10:54:50.382Z"}
Fields
| Field | Meaning | Example |
|---|---|---|
recallKey | Stable key: category:recallNumber. For not yet classified recalls: category:unclassified:eventId:hash. Use it to join and compare. | "food:H-1395-2026" |
recallNumber | FDA recall number. null while FDA has not classified the recall. | "D-0860-2026" |
eventId | FDA recall event. One event can cover several products. | "99874" |
category, productType | Searched category, and the product type as FDA writes it | "food", "Food" |
classification, recallClass | FDA class text and short form (I, II, III, or null if not classified yet) | "Class I", "I" |
status | Ongoing, Completed or Terminated | "Ongoing" |
recallingFirm and address1, address2, city, state, postalCode, country | Firm that recalls the product, and its address | "WFM Purchasing, LP" |
productDescription, productQuantity | What is recalled and how much | "21 Wheels" |
codeInfo, moreCodeInfo | Lot numbers, dates, UPCs, as the firm gave them | "Lot 12345" |
reasonForRecall | Why FDA lists the recall | "Undeclared Egg Allergen" |
distributionPattern | Where the product was distributed, free text | "Nationwide" |
voluntaryMandated, initialFirmNotification | Who started the recall and how the firm told customers | "Voluntary: Firm initiated" |
recallInitiationDate, centerClassificationDate, reportDate, terminationDate | The four FDA dates, YYYY-MM-DD, no time zone shift | "2026-09-30" |
drugBrandNames, drugGenericNames, drugProductNdcs | Drug rows only, from openFDA's drug data. null for food and devices. | drugGenericNames: ["SODIUM CHLORIDE"] |
changeType | initial (first monitor run), new, updated, unchanged, or null without a comparison | "updated" |
changedFields, previousValues | For updated: which fields changed and their old values | ["status", "terminationDate"] |
sourceUrl | This record in the openFDA API | "https://api.fda.gov/..." |
provider, sourceUpdatedAt, fetchedAt | Data provider, openFDA's last update date, and our read time | "2026-09-30" |
null means FDA has no value. It never means zero, and an empty list is never shown as a value.
A recall is updated when one of these fields changes: status, classification, the four dates, recallingFirm, productDescription, productQuantity, codeInfo, reasonForRecall, distributionPattern, voluntaryMandated.
Run summary
RUN_SUMMARY.status is one of:
| Status | Meaning | Run result |
|---|---|---|
COMPLETE | Rows were written. truncated: true means openFDA has more recalls than maxResults. | succeeded |
NO_RESULTS | openFDA answered, and no recall matches your filters. This is not an error. | succeeded |
NO_CHANGES | Comparison run: no new or updated recalls. | succeeded |
PARTIAL | Some categories failed or time ran out. The rows you got are correct. | succeeded |
CAPPED | Your maximum cost per run was reached. | succeeded |
ERROR | openFDA was not available, refused the request (rate limit) or changed its format. This is not an empty result. | failed |
INVALID_INPUT | The input is wrong, or previousDatasetId was not found. message explains why. | failed |
RUN_SUMMARY also has counts (fetched, written, charged, initial, new, updated, unchanged), one categories entry per category with its own status and matchedAtSource, the filters used, the comparison baseline, warnings, and the data source with licence and attribution.
Pricing
Pay per event. Platform usage is included.
| Event | Price | When |
|---|---|---|
| Actor start | $0.002 | Once per run (per GB of memory; the default 256 MB counts once) |
| Recall record | $0.0001 | Each recall row written to the Dataset (a bit less on higher Apify plans) |
Unchanged recalls hidden by onlyChanges are free. A run with no results, no changes, an input error or an openFDA error costs only the start.
| Run | Example cost |
|---|---|
| 10 recalls | $0.003 |
| 20 recalls (form example) | $0.004 |
| 100 recalls | $0.012 |
| 1,000 recalls | $0.102 |
| up to 3,000 recalls (3 categories × 1,000) | up to $0.302 |
| Weekly monitor run with 5 changes | $0.0025 |
| No results or no changes | $0.002 |
Set a maximum cost per run in the run options to cap your spend. The Actor stops before a row that does not fit and reports CAPPED.
Monitoring on a schedule
- Save your input as a task and add a
monitorKey, for examplefood-class-1. - Add an Apify schedule to the task, for example every Monday (FDA publishes the Enforcement Report weekly, usually on Wednesday).
- The first run marks all rows
initial. Each later run writes onlynewandupdatedrecalls. - Send the rows to email, Slack, Google Sheets or a webhook with Apify integrations.
The range moves with the run date. A recall that later changes but is now outside your range is not seen. To catch recalls that FDA closed, run a second task with dateField: "termination_date". This is a convenience tool, not an official FDA alert service, and it does not promise that you get every recall or get it in time.
API and integrations
Start a run with the same JSON input through the Apify API (POST /v2/acts/cliqtomedia~fda-recalls-enforcement-monitor/runs), then read the Dataset. Export to CSV, Excel or JSON, or send rows to Google Sheets, Slack or a webhook with Apify integrations. Join rows on recallKey.
Use with AI agents (MCP)
AI agents can call this Actor through the Apify MCP server: add https://mcp.apify.com?tools=cliqtomedia/fda-recalls-enforcement-monitor to your MCP client (Claude, Cursor, VS Code and others). The MCP server needs your Apify account (OAuth sign-in or an Apify API token); openFDA itself needs no key. The agent builds the input from the input schema. The smallest useful input:
{ "categories": ["drug"], "classifications": ["I"], "maxResults": 10 }
Key output fields for an agent: recallNumber, classification, status, recallingFirm, productDescription, reasonForRecall, reportDate, sourceUrl, and RUN_SUMMARY.status. A call with 10–1,000 recalls usually finishes in under 10 seconds and costs $0.003–$0.102.
Limits
- Up to 1,000 recalls per category and 3 categories, so up to 3,000 rows per run. In our test, 2,541 rows took about 4 seconds.
- The date range is at most 90 days. Enforcement Reports start in 2004.
- Without a key, openFDA limits requests per IP address per day, and the IP can be shared with other users. Each category is one request. If openFDA refuses with a rate limit, the run stops with
ERRORand a hint. Add your freeopenFdaApiKeyto get your own quota. - If openFDA does not answer (up to 30 seconds per try, at most 3 tries and 2 timeouts), the run stops early and does not ask for the other categories. You get the rows found so far. The internal time budget is 240 seconds.
- Monitor snapshots keep up to 20,000 recalls per
monitorKey.previousDatasetIdreads up to 20,000 rows. - Not yet classified recalls have no recall number. When FDA classifies them, they come back with a recall number as a
newrow with a newrecallKey. firmStatesis the firm's address, not where the product was sold.- openFDA updates the enforcement data about once a week.
sourceUpdatedAtshows the last update.
Troubleshooting
| Symptom | Check | Action |
|---|---|---|
NO_RESULTS | RUN_SUMMARY.filters | Widen the dates, remove a class or a filter, or try another dateField. |
ERROR with a rate limit message | RUN_SUMMARY.message | Add your free openFdaApiKey, or run again later. |
ERROR, openFDA unavailable | RUN_SUMMARY.message | Run again later. A failed run does not remove recalls from your monitor snapshot; it only adds the rows it reported. |
INVALID_INPUT | RUN_SUMMARY.message | Fix the field named in the message. The range is at most 90 days. |
truncated: true | categories[].matchedAtSource | Raise maxResults (up to 1,000) or narrow the filters or dates. |
| A recent recall is missing | sourceUpdatedAt, reportDate | FDA adds recalls to the weekly report after classification. Try dateField: "recall_initiation_date" and include unclassified. |
| Warning about different filters | RUN_SUMMARY.warnings | You changed filters but kept the same monitorKey. Use one key per saved search. |
FAQ
Is this medical advice?
No. It is FDA data as published. For decisions about a product you use, follow FDA, the firm, and your doctor or pharmacist.
Where does the data come from?
From openFDA, the official open data API of the U.S. Food and Drug Administration. The records are the FDA Enforcement Reports.
Do I need an API key?
No. A free openFDA key is optional and only gives you your own request quota.
What are Class I, II and III?
Class I: a reasonable chance of serious health problems or death. Class II: temporary or reversible health problems. Class III: unlikely to cause health problems. "Not yet classified" means FDA has not set the class yet.
How fresh is the data?
Each run reads openFDA live. openFDA updates the enforcement data about once a week, after FDA publishes the Enforcement Report. Firm press releases can come earlier.
Does monitoring cost more?
No. Unchanged recalls are not written and not charged when onlyChanges is on.
Why are there no device codes like GMDN?
GMDN terms have their own licence, so the Actor does not output openFDA device classification data. If a firm wrote a code into its own codeInfo text, it stays as FDA published it.
Data source and licence
Data provided by the U.S. FDA (open.fda.gov). openFDA data is in the public domain under CC0 1.0; GMDN device terms are excluded and never output. This Actor is independent and not affiliated with or endorsed by the U.S. Food and Drug Administration. Do not rely on it for medical decisions.
Related Actors
- VIN Decoder & Vehicle Recalls — NHTSA vehicle recalls by VIN.
- USAspending Federal Awards & Recipient Monitor — federal contracts and grants, with change monitoring.
Support
Use the Issues tab of this Actor. Add the run ID, your input (without private data or your openFDA key) and RUN_SUMMARY.status and message. Do not send API tokens.