FDA Warning Letters, Recalls & Import Alerts Monitor
Pricing
Pay per usage
FDA Warning Letters, Recalls & Import Alerts Monitor
Get new FDA warning letters, recalls, enforcement reports and import alerts in one dataset. Watch suppliers by name or FEI. Schedule it daily.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Northline Data Systems
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Features
Share
One run pulls new FDA warning letters, drug, device and food recalls, enforcement reports and import alerts into a single table with the same columns. Put your suppliers or competitors on a watchlist (by name or FEI number), turn on "only new," and schedule it daily. You get just the records you haven't seen yet, each with a link back to the FDA page.
Three ways to use it
- Monitor: new records from the sources you pick, filtered by company, product or keyword.
- Firm check: paste up to 25 firm names or FEI numbers and see every warning letter, recall, enforcement report and import alert listing that matches.
- Import alert changes: watch alerts such as 66-80 or 66-40 and get told when a firm is added to or removed from a list.
Pricing: the Actor itself is free. Like any Actor, a run uses Apify platform resources, which are billed to your account under your normal Apify plan.
Sources
| Source key | Where it comes from | What you get |
|---|---|---|
warning_letters | fda.gov Warning Letters listing | Company, issuing office, subject, letter date, posted date, link to the letter |
import_alerts | FDA Import Alerts index (accessdata.fda.gov) | Alerts published or updated in your date range: number, type (e.g. DWPE), name, link |
drug_enforcement | FDA Enforcement Reports for drugs (openFDA) | Recall number, firm, product, class, reason, status, dates |
device_enforcement | FDA Enforcement Reports for devices (openFDA) | Same fields |
food_enforcement | FDA Enforcement Reports for food (openFDA) | Same fields |
device_recalls | CDRH Medical Device Recalls (openFDA) | Recall number, firm, FEI number, product, reason, status, dates, link to the FDA recall page |
Overnight window for accessdata.fda.gov
The robots.txt for accessdata.fda.gov asks crawlers to visit only between 11 PM and 5 AM US Eastern. The Actor follows that. Import alert pages (the import_alerts source, the import_alert_changes mode, and the live import alert check in firm_check) are read only from 23:00 to 05:00 America/New_York. Outside that window they are skipped, and the log, the status message and RUN_SUMMARY say so and give the time the window opens. openFDA and fda.gov sources can run at any hour. If you use import alerts, schedule the run for around 00:30 Eastern.
Modes
Choose a mode with the mode input.
| Mode | What it does |
|---|---|
monitor (default) | Returns recent records from the sources you select. |
import_alert_changes | Watches the import alerts you list (for example 66-80, GLP-1 APIs, or 66-40, drug CGMP) and reports what changed since the previous run: firms added to or removed from a Red, Green or Yellow List, firms moved between lists, changes to a firm's product codes, country-wide product codes added or removed, and the alert being republished. |
firm_check | Looks up firm names or FEI numbers across warning letters, import alert firm lists, drug, device and food enforcement reports, and device recalls. Each match includes the source, record ID, date and link. |
import_alert_changes
- The first run for an alert only saves a baseline and returns no rows for it. The log, status message and
RUN_SUMMARY(baseline_alerts) note this. Changes show up from the second run on, so this mode is meant to be scheduled, for example daily. - State is kept in a named key-value store in your account,
fda-import-alert-state, with one record per alert. Delete a record to re-baseline that alert. - Every change found is also written to the
LAST_CHANGESrecord in the run's key-value store. Up to Max records of them go to the dataset. - Inputs:
importAlertNumbers(default["66-80"], up to 10 per run),maxItems, and optionallywatchlistandonlyWatchlistMatches.
{ "mode": "import_alert_changes", "importAlertNumbers": ["66-80", "66-40"] }
firm_check
- Inputs:
firms(up to 25 names or 7 to 10 digit FEI numbers),maxResultsPerSource(default 10),importAlertNumbers(default["66-80", "66-40"]),checkWarningLetters,checkImportAlerts,maxItems. - Name matching ignores case, punctuation and suffixes such as Inc, LLC and Ltd. Every word in your query has to appear in the firm name FDA lists. FDA's warning letter search is full-text, so a letter is kept only when its company name matches.
- FEI numbers can be matched only where FDA publishes them: device recalls (
fei_number) and the text of warning letters (match_type: fei_in_letter_text). Enforcement reports and import alert pages don't show FEI numbers. - Import alert matches come from the alerts you list, read live, plus any alerts already saved by
import_alert_changesruns. The snapshot time is given inRUN_SUMMARY. - There is no date filter. Everything the sources return is searched, newest first.
- A per-firm summary, including firms with no matches, is saved to
FIRM_CHECK_SUMMARY.
{ "mode": "firm_check", "firms": ["Hims & Hers Health", "Babikian Healthcare", "1000517638"] }
These two modes add the fields mode, change_type, alert_number, list_type, country, address, previous_value, products, matched_query and match_type. The dataset has changes and firmCheck table views for them.
Why this one
Most FDA actors cover one source. This one reads six (fda.gov warning letters, the import alert index, and four openFDA endpoints) and returns them in one schema. That means a single schedule and a single watchlist for all of it. It follows fda.gov's crawl-delay and only reads accessdata.fda.gov pages in the overnight window that site's robots.txt asks for, so import-alert runs should be scheduled for around 00:30 Eastern.
Typical uses
- Supplier and competitor watch: put supplier names or FEI numbers on a watchlist and return only the matches.
- A daily compliance feed: schedule a run with Only new records on, and send the results to Slack, email, Google Sheets or a webhook through Apify integrations, Make or Zapier.
- Research: pull 30 to 365 days of warning letters or recalls for a product category.
- Data pipelines: one stable JSON schema with source links, ready for a database or dashboard.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
mode | text | monitor | monitor, import_alert_changes or firm_check |
sources | list | warning_letters, food_enforcement | Which of the six sources to read (monitor mode) |
lookbackDays | integer, 1 to 365 | 7 | How many days back to look. Ignored when dateFrom is set |
dateFrom / dateTo | date (YYYY-MM-DD) | none | Optional fixed range, matched against posted_date |
watchlist | list of text | empty | Company names, products, FEI numbers or keywords, matched case-insensitively |
onlyWatchlistMatches | true/false | false | Return only records that match the watchlist |
onlyNew | true/false | false | Skip records that earlier runs already returned (see Limits) |
maxItems | integer, 1 to 5000 | 25 | The most records one run returns |
openFdaApiKey | secret text | none | Optional free openFDA key for heavy use |
Example:
{"sources": ["warning_letters", "device_enforcement", "device_recalls"],"lookbackDays": 14,"watchlist": ["Medtronic", "CGMP"],"onlyWatchlistMatches": true,"onlyNew": true,"maxItems": 200}
Output
Each record has the fields below. Missing values are null.
| Field | Meaning |
|---|---|
source | The source key the record is reported under |
sources | Every feed the record was found in this run, e.g. ["device_enforcement", "device_recalls"] |
record_id | FDA's ID: recall number (D-, Z-, F-, H-), WL- + letter ID, or IA- + alert number. A tmp- ID when FDA hasn't assigned one yet |
id_is_provisional | true when record_id is a temporary tmp- ID |
title | Short human-readable title |
firm_name | Company named by FDA (not given for alert-level import alert rows in monitor mode) |
fei_number | FDA Establishment Identifier, published only in device recalls |
product_type | Drugs, Devices, Food, etc. For warning letters it is derived from the issuing office |
classification | Recall class (Class I/II/III), or the alert type (e.g. DWPE) for import alerts |
reason | Recall reason or warning-letter subject |
status | Recall status, or for warning letters whether FDA posted a response or closeout letter |
issuing_office | FDA office or report name |
event_date | When the underlying event happened (see Dates below). null for import alert rows in monitor and firm_check |
posted_date | When FDA posted, reported or published it (see Dates below). Date filters and sorting use this field |
url | Link to the official FDA source |
fetched_at | When the Actor read it (UTC) |
watchlist_match / matched_terms | Whether, and on which terms, the record matched your watchlist |
Dates: posted_date vs event_date
| Mode / source | posted_date | event_date |
|---|---|---|
warning_letters (monitor, firm_check) | Date the letter was posted on fda.gov | Letter issue date |
drug/device/food_enforcement (monitor, firm_check) | Enforcement report date (report_date) | Recall initiation date |
device_recalls (monitor, firm_check) | Date FDA posted the recall (event_date_posted) | Recall initiation date (event_date_initiated) |
import_alerts in monitor (alert level) | Alert's publish/update date on the import alert index | null |
import_alerts in firm_check | The firm's "Date Published" on the alert | null |
import_alert_changes | The firm's "Date Published" on the alert; for product or republish rows, the alert's publish date | Date (UTC) this Actor detected the change |
In monitor mode, lookbackDays, dateFrom and dateTo filter on posted_date, so a recall initiated months ago appears when FDA reports it. firm_check has no date filter. When a device recall is merged across feeds, the dates come from the enforcement report.
Enforcement-report records link to the openFDA API record, because FDA publishes no stable web page for each one. Merged device recalls link to the public CDRH recall page.
Example output record
{"source": "device_enforcement","record_id": "Z-0190-2027","title": "Class II: The ABL90 FLEX and ABL90 FLEX PLUS analyzers are intended for use by trained technologists, nurses, physicians and therapists. It is intended for use in a labor","firm_name": "Radiometer Medical ApS","fei_number": "3002807968","product_type": "Devices","classification": "Class II","reason": "In vitro diagnostic analyzer had a risk of potentially inaccurate results requiring changes to instructions for use and: 1) Sample types, including whole blood samples no longer suitable for testing FHbF and ctBil, 2) Reportable ranges for some parameters, 3) Analyzer configuration, and 4) limitations and warnings.","status": "Ongoing","issuing_office": "FDA Enforcement Report (via openFDA)","event_date": "2026-08-18","posted_date": "2026-10-21","url": "https://www.accessdata.fda.gov/scripts/cdrh/cfdocs/cfRES/res.cfm?id=222446","fetched_at": "2026-10-28T01:56:36+00:00","watchlist_match": false,"matched_terms": [],"sources": ["device_enforcement","device_recalls"],"id_is_provisional": false}
See the Output tab for more sample records from every source.
Limits
- Duplicates are merged only within a run. A device recall found in both openFDA device enforcement and CDRH device recalls is returned once, with
sourceslisting both feeds. Separate runs don't check against each other unless Only new records is on. - Only new records remembers up to the 50,000 most recent IDs in a named key-value store in your account. Deleting that store resets it.
- openFDA sometimes publishes a recall before FDA assigns its number. Those records get a stable
tmp-ID andid_is_provisional: true. When the real number is assigned later, the same recall can come back once under it. - fda.gov and accessdata.fda.gov ask crawlers to wait 30 seconds between requests, and the Actor does. Each extra page of about 100 warning letters adds about 30 seconds. openFDA sources are fast.
- openFDA allows 1,000 requests per day per IP without a key. Add your own free key for heavy use.
- The Actor reads listings only. It does not download letter bodies or attachments. In
monitormode import alerts are reported at the alert level.import_alert_changesandfirm_checkread firm lists only on the alert pages you choose, 30 seconds apart, so one run does not cover all of the roughly 150 alerts. - Some alert pages are large (66-41 is about 6.7 MB with about 1,900 firms). Some alerts, such as 66-80, list products country-wide rather than naming firms, so changes show up as product rows. Firm entries on alert pages carry no FEI number. Red List parsing was tested on live pages. Green and Yellow List headings are detected by their wording but did not appear on the pages tested.
- Crawl hours: accessdata.fda.gov's robots.txt has
Visiting-hours: 23:00EDT-05:00EDT. The Actor applies it as 23:00 to 05:00 America/New_York local time (EDT in summer, EST in winter) and never reads accessdata.fda.gov outside it. There is no override. A run still going at 05:00 stops reading import alert pages and lists the ones it skipped.import_alert_changesstarted outside the window exits without reading anything or changing saved state.firm_checkoutside the window still checks openFDA, warning letters and import alert snapshots saved by earlier runs. Device recall links to the CDRH recall page (res.cfm) are links only and are never fetched. - FDA publishes on its own schedule, and openFDA can lag fda.gov by several days. Coverage is not guaranteed to be complete. Check the linked FDA record before relying on a result.
Data source and disclaimer
Data comes from the U.S. Food and Drug Administration. openFDA data is CC0 public domain (https://open.fda.gov/terms/), and fda.gov content is public domain under FDA's Website Policies. Records are reproduced as published, with a link and the time they were fetched.
This Actor is not affiliated with or endorsed by FDA, and its output is not legal, regulatory or medical advice.
Published by Northline Data Systems.