FDA Recalls & Enforcement Monitor: openFDA Reports avatar

FDA Recalls & Enforcement Monitor: openFDA Reports

Pricing

from $0.07 / 1,000 recall records

Go to Apify Store
FDA Recalls & Enforcement Monitor: openFDA Reports

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

Cliqto Media

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

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.

FDA Recalls & Enforcement Monitor: category, class and date filters in, one row per recalled product out with four separate FDA dates, plus new and updated recalls since the last run

Contents

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. maxResults applies 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) and terminationDate (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 recallKey anyway.
  • Monitoring. With a monitorKey, the Actor saves the recalls it saw in your account. The next run marks each recall new, updated (for example the status changed to Terminated) or unchanged, 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 CA or NJ.
  • 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

  1. Open the Input tab. The form already has an example: food, Class I, last 30 days, 20 recalls.
  2. Click Start.
  3. Open the Recalls view in the Output tab. Check recallNumber, recallingFirm, productDescription, reasonForRecall and reportDate.
  4. Change the categories, classes or filters to your own. To get only changes next time, add a monitorKey such as food-class-1.

Expected result: up to 20 recall rows in a few seconds, newest first.

Use cases

Buyer jobInputOutputKey fields
Weekly food safety watchcategories: ["food"], classifications: ["I"], monitorKey, on a scheduleonly new and updated Class I recallschangeType, reasonForRecall, distributionPattern
Supplier checkfirmNames, all categories, a 90-day rangethat firm's recallsrecallingFirm, productDescription, status
Allergen or pathogen researchreasonQuery: "Listeria" or "undeclared peanut"matching recallsreasonForRecall, codeInfo, productQuantity
Medical device recall searchcategories: ["device"], productQuery, firmStatesdevice recall rowsrecallNumber, classification, centerClassificationDate
Drug recall list with NDCscategories: ["drug"]drug rowsdrugBrandNames, drugGenericNames, drugProductNdcs
Closed recallsdateField: "termination_date"recalls FDA terminated in the rangeterminationDate, status

Input

All filters are optional and combine with AND. Values inside one list combine with OR.

FieldTypeDefaultAllowed valuesWhat it does
categoriesarray["food"]food, drug, deviceWhich openFDA endpoints to search. food also has cosmetics and dietary supplements.
classificationsarrayallI, II, III, unclassifiedFDA recall class. Class I is the most serious. unclassified = not yet classified. Empty = all.
statusesarrayallOngoing, Completed, TerminatedRecall status. Empty = all.
lookbackDaysinteger301–90Days back from dateTo. Ignored when dateFrom is set.
dateFieldstringreport_datereport_date, recall_initiation_date, center_classification_date, termination_dateWhich FDA date the range uses.
dateFrom, dateTodatedateTo = today (UTC)YYYY-MM-DD, from 2004Exact range, at most 90 days. Split longer periods into several runs.
firmNamesarray of stringsnoneup to 10; 2–120 charactersPhrase in the recalling firm name. Whole Foods matches Whole Foods Market Group Inc.
productQuerystringnone2–120 charactersPhrase in the product description, like ice cream or insulin pump.
reasonQuerystringnone2–120 charactersPhrase in the reason for recall, like Listeria or undeclared milk.
firmStatesarray of stringsnoneup to 20 two-letter codesState of the recalling firm, like CA. It is not where the product was sold; see distributionPattern.
maxResultsinteger1001–1000Maximum recalls per category, newest first.
monitorKeystringnone1–40 letters, digits or dashesSaves this run's recalls and compares the next run with them. One key per saved search.
previousDatasetIdstringnonedataset IDCompares with the dataset of an earlier run of this Actor. Use this or monitorKey, not both.
onlyChangesbooleantrueWith a comparison, skip unchanged recalls. You do not pay for skipped recalls.
openFdaApiKeystring (secret)noneyour free openFDA keyOptional. 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

FieldMeaningExample
recallKeyStable key: category:recallNumber. For not yet classified recalls: category:unclassified:eventId:hash. Use it to join and compare."food:H-1395-2026"
recallNumberFDA recall number. null while FDA has not classified the recall."D-0860-2026"
eventIdFDA recall event. One event can cover several products."99874"
category, productTypeSearched category, and the product type as FDA writes it"food", "Food"
classification, recallClassFDA class text and short form (I, II, III, or null if not classified yet)"Class I", "I"
statusOngoing, Completed or Terminated"Ongoing"
recallingFirm and address1, address2, city, state, postalCode, countryFirm that recalls the product, and its address"WFM Purchasing, LP"
productDescription, productQuantityWhat is recalled and how much"21 Wheels"
codeInfo, moreCodeInfoLot numbers, dates, UPCs, as the firm gave them"Lot 12345"
reasonForRecallWhy FDA lists the recall"Undeclared Egg Allergen"
distributionPatternWhere the product was distributed, free text"Nationwide"
voluntaryMandated, initialFirmNotificationWho started the recall and how the firm told customers"Voluntary: Firm initiated"
recallInitiationDate, centerClassificationDate, reportDate, terminationDateThe four FDA dates, YYYY-MM-DD, no time zone shift"2026-09-30"
drugBrandNames, drugGenericNames, drugProductNdcsDrug rows only, from openFDA's drug data. null for food and devices.drugGenericNames: ["SODIUM CHLORIDE"]
changeTypeinitial (first monitor run), new, updated, unchanged, or null without a comparison"updated"
changedFields, previousValuesFor updated: which fields changed and their old values["status", "terminationDate"]
sourceUrlThis record in the openFDA API"https://api.fda.gov/..."
provider, sourceUpdatedAt, fetchedAtData 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:

StatusMeaningRun result
COMPLETERows were written. truncated: true means openFDA has more recalls than maxResults.succeeded
NO_RESULTSopenFDA answered, and no recall matches your filters. This is not an error.succeeded
NO_CHANGESComparison run: no new or updated recalls.succeeded
PARTIALSome categories failed or time ran out. The rows you got are correct.succeeded
CAPPEDYour maximum cost per run was reached.succeeded
ERRORopenFDA was not available, refused the request (rate limit) or changed its format. This is not an empty result.failed
INVALID_INPUTThe 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.

EventPriceWhen
Actor start$0.002Once per run (per GB of memory; the default 256 MB counts once)
Recall record$0.0001Each 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.

RunExample 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

  1. Save your input as a task and add a monitorKey, for example food-class-1.
  2. Add an Apify schedule to the task, for example every Monday (FDA publishes the Enforcement Report weekly, usually on Wednesday).
  3. The first run marks all rows initial. Each later run writes only new and updated recalls.
  4. 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 ERROR and a hint. Add your free openFdaApiKey to 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. previousDatasetId reads 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 new row with a new recallKey.
  • firmStates is the firm's address, not where the product was sold.
  • openFDA updates the enforcement data about once a week. sourceUpdatedAt shows the last update.

Troubleshooting

SymptomCheckAction
NO_RESULTSRUN_SUMMARY.filtersWiden the dates, remove a class or a filter, or try another dateField.
ERROR with a rate limit messageRUN_SUMMARY.messageAdd your free openFdaApiKey, or run again later.
ERROR, openFDA unavailableRUN_SUMMARY.messageRun again later. A failed run does not remove recalls from your monitor snapshot; it only adds the rows it reported.
INVALID_INPUTRUN_SUMMARY.messageFix the field named in the message. The range is at most 90 days.
truncated: truecategories[].matchedAtSourceRaise maxResults (up to 1,000) or narrow the filters or dates.
A recent recall is missingsourceUpdatedAt, reportDateFDA adds recalls to the weekly report after classification. Try dateField: "recall_initiation_date" and include unclassified.
Warning about different filtersRUN_SUMMARY.warningsYou 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.

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.