Product Recall Radar - FDA, CPSC & USDA Recalls API
Pricing
Pay per usage
Product Recall Radar - FDA, CPSC & USDA Recalls API
Know within the hour when a product you sell, stock, or insure is recalled. It monitors all US federal authorities (FDA, CPSC, USDA) and delivers unified records with a single severity scale, catalogue barcode matching, built-in change detection, and verified source delivery.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Alessandro Sirsi
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
13 days ago
Last modified
Categories
Share
Product Recall Radar — FDA, CPSC & USDA Recalls API
Know within the hour when a product you sell, stock or insure is recalled.
A single endpoint that monitors every US federal recall authority in real time and tells you — in one consistent format — what was recalled, how serious it is, and whether it touches your catalogue.
The problem this removes
A recall becomes your problem the moment it is published, not the moment you happen to notice it. Between publication and detection sit the products still on your shelves, still in your listings, still shipping to customers.
Detection is hard for a boring reason: the information is scattered across four federal authorities that share no common format, no common severity scale and no common identifier. Building and maintaining that reconciliation layer is weeks of engineering, and it breaks quietly every time an agency changes a field.
This Actor is that layer, kept working for you.
What you get
One schema across every authority. Food, pharmaceuticals, medical devices, consumer products, meat and poultry arrive as identical records. Write your integration once.
Catalogue matching. Send your UPC/EAN/GTIN codes and receive only the recalls that hit your products, each tagged with which of your codes matched. Barcode formats are normalized, so a UPC-12 in your system matches an EAN-13 in a government notice.
A single severity scale. Three agencies, three different classification systems, one comparable severity field — so one alerting rule covers all of them.
Change detection built in. Incremental mode remembers what it has already delivered. Schedule it hourly and each run returns only what is new. No diffing on your side, no duplicate alerts at 3am.
Verified delivery. Every run reports which authorities actually answered. Silence and "nothing was recalled" are different facts, and this feed never confuses the two.
Traceability. Every record links back to the authoritative government notice, so any decision you take from this feed can be evidenced.
Quick start
curl -X POST "https://api.apify.com/v2/acts/alessandrosir~product-recall-radar/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"regions": ["US"],"daysBack": 7,"severities": ["high"],"onlyActive": true}'
Watch your own catalogue:
-d '{"regions": ["US"],"productCodes": ["0736659265018", "029361000000"],"incremental": true}'
Only recalls affecting those barcodes come back — each with a matched_codes field naming the product involved.
Reproduce an exact reporting window:
$-d '{"regions":["US"],"dateFrom":"2026-01-01","dateTo":"2026-06-30"}'
Who uses it
Marketplaces and retailers — flag or delist affected listings before a customer buys one. Grocery and food service — know about a contamination notice the same hour it is issued. Compliance and quality teams — a defensible, timestamped record of what was published and when you saw it. Insurers and risk analysts — recall frequency by company as a measurable risk signal. AI agents and RAG pipelines — current, citable safety data instead of a model's recollection.
Coverage
| Source key | Authority | Scope |
|---|---|---|
openfda_food | FDA | Food & beverage |
openfda_drug | FDA | Pharmaceuticals |
openfda_device | FDA | Medical devices |
cpsc | CPSC | Consumer products |
fsis | USDA FSIS | Meat, poultry, eggs — see note |
Set regions: ["US"] to monitor all generally available authorities.
On USDA FSIS: the agency's endpoint and its public mirrors reject requests from datacenter IP ranges, so the source is unreachable from shared cloud infrastructure. It is fully implemented and enabled by adding "sources": ["fsis"] when you run from your own infrastructure or through a residential proxy. It is left out of the default region so a standard run never returns an incomplete result without saying so. European authorities (RASFF / Safety Gate) are in development — every record already carries source_country, so adding a region will not change your integration.
Output schema
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | no | Stable unique id. Safe to deduplicate and store as a key. |
source | string | no | Issuing authority key. |
source_country | string | no | ISO country code. |
category | string | no | food, drug, device, consumer_product, meat_poultry. |
title | string | yes | Readable headline, ~140 chars. |
product_description | string | yes | Full product text when the title was shortened. |
reason | string | yes | The hazard or defect. |
company | string | yes | Recalling firm. |
brand_names | string[] | no | Brands named by the authority. |
classification | string | yes | The authority's own wording, e.g. Class I. |
severity | string | no | high, medium, low, unknown. |
severity_source | string | no | agency when officially published, none when the authority publishes none. |
hazards | string[] | no | Hazard labels as published. |
status | string | yes | e.g. Ongoing, Terminated, Active. |
recall_date | string | yes | YYYY-MM-DD. |
distribution | string | yes | Where the product was distributed. |
quantity | string | yes | Units affected. |
url | string | yes | Link to the authoritative notice. |
identifiers.codes | string[] | no | Product codes found in the notice. |
identifiers.matched_codes | string[] | when matching | Which of your codes this recall hits. |
retrieved_at | string | no | ISO 8601 UTC. |
raw | object | with includeRaw | Original payload. |
Example record
{"id": "openfda_food:F-0890-2026","source": "openfda_food","source_country": "US","category": "food","title": "White Cheddar Seasoning, Net Wt. 1.6 oz (45g), UPC 7 36659-26501 8…","product_description": "White Cheddar Seasoning packaged in the following sized containers: …","reason": "Products may be potentially contaminated with Salmonella.","company": "JCB Flavors, LLC","brand_names": [],"classification": "Class I","severity": "high","severity_source": "agency","hazards": [],"status": "Ongoing","recall_date": "2026-05-01","distribution": "KS, MN, NY, WI","quantity": "5200 jars total","url": "https://api.fda.gov/food/enforcement.json?search=recall_number:\"F-0890-2026\"","identifiers": { "codes": ["736659265018"] },"retrieved_at": "2026-08-09T09:00:00+00:00"}
Setting up monitoring
- Set
incremental: true,regions: ["US"],onlyActive: true. - Schedule the Actor hourly or daily.
- Add a webhook on run success.
Each run then delivers only what is new. Narrow it further with productCodes to be alerted solely about your own products, or severities: ["high"] for life-safety events.
Changed your filters and want the window re-delivered? Run once with resetState: true, then switch it off.
Run summary
Every run writes an OUTPUT object to the default key-value store:
{"partial": false,"sources_ok": ["openfda_food", "openfda_drug", "openfda_device", "cpsc", "fsis"],"sources_failed": [],"total_emitted": 285,"new_records": 285,"high_severity": 61,"by_severity": { "high": 61, "medium": 162, "low": 4, "unknown": 58 },"by_source": { "openfda_device": 116, "openfda_drug": 57, "cpsc": 53, "openfda_food": 50, "fsis": 9 },"window_start": "2026-07-10","window_end": null,"skipped_already_delivered": 0,"skipped_by_filters": 0,"only_active": false,"incremental": true,"finished_at": "2026-08-09T19:49:56Z"}
partial is the field to check before acting on a run. An empty result can mean nothing was recalled — or that an authority was unreachable. Feeds that do not distinguish the two will let you report "all clear" on a day you simply failed to look. When partial is true, sources_failed names the authority and the reason. A single source failing never aborts the run.
For AI agents
Recall status is exactly the question a language model should never answer from memory: it changes daily and a wrong answer has consequences.
- Every record carries a
urlto the authoritative notice, so answers are citable. severity_sourcedistinguishes an official classification from an absent one, so the agent never presents a guess as an agency decision.partiallets the agent say "I could not reach the FDA just now" instead of "there are no recalls" — the difference between a cautious assistant and a dangerous one.
Input reference
| Option | Type | Default | Purpose |
|---|---|---|---|
regions | string[] | ["US"] | Jurisdictions to monitor. |
sources | string[] | — | Advanced: individual authorities. Ignored when regions is set. |
daysBack | integer | 30 | Look-back window on a first run. |
dateFrom | string | — | YYYY-MM-DD. Overrides daysBack; use for backfills. |
dateTo | string | — | YYYY-MM-DD. Upper bound. |
incremental | boolean | true | Deliver only records not seen in previous runs. |
resetState | boolean | false | Clear the delivery memory once. |
keywords | string[] | — | Free-text filter across title, reason, company, brands. |
classifications | string[] | — | Class I / II / III. |
severities | string[] | — | high / medium / low / unknown. |
onlyActive | boolean | false | Exclude terminated, completed and closed recalls. |
productCodes | string[] | — | Your barcodes. Returns only recalls affecting them. |
openFdaApiKey | string | — | Free FDA key; raises the request ceiling. |
maxItems | integer | 1000 | Cap per run. |
includeRaw | boolean | false | Attach the original payload. |
Reliability
- Requests retry with exponential backoff on connection failures, rate limits and gateway errors.
- Each authority is isolated: one failing never aborts a run.
- Records are deduplicated within a run and across runs.
- The USDA source tries the official API first and falls back to public government mirrors automatically. Records from a mirror carry fewer fields — no recall number or classification — and arrive with
severity: "unknown". - An empty result is always explained. The run summary reports how many records were withheld because a previous run already delivered them (
skipped_already_delivered) and how many your filters excluded (skipped_by_filters), so "nothing new" is never ambiguous.
Notes
- Coverage is United States in this version.
severityreflects only what the issuing authority published. CPSC does not publish a severity level, so those records carryseverity: "unknown"; use thehazardsfield to apply your own rules. Severity is never inferred from wording.- USDA publishes currently listed recalls rather than a deep archive, so a long look-back has limited effect there.
- This feed is monitoring infrastructure, not a substitute for an authority's own notification channels. Verify against the linked notice before acting on a specific case.
Sources
Data originates from the official US federal recall authorities: FDA (openFDA), the Consumer Product Safety Commission, and USDA Food Safety and Inspection Service. No personal data is collected, processed or returned.