FDA Medical Device Recall Search
Pricing
from $2.00 / 1,000 recall fetcheds
FDA Medical Device Recall Search
FDA Medical Device Recall Search queries the U.S. Food and Drug Administration's openFDA device enforcement endpoint to retrieve detailed, structured data about medical device recalls.
Pricing
from $2.00 / 1,000 recall fetcheds
Rating
0.0
(0)
Developer
Ryan Clinton
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
2
Monthly active users
5 days ago
Last modified
Categories
Share

Medical device recall monitoring, supplier risk scoring, and inventory exposure intelligence. Powered by FDA recall and adverse-event data. Know which recalls matter, which suppliers are getting riskier, and whether your inventory is affected, in a single API call.
Most recall tools tell you a recall happened. This actor tells you what to do about it -- is it high risk, is it part of a recurring failure pattern, is the manufacturer deteriorating, does it affect your inventory, what changed since yesterday, and what action to take. Every recall arrives as a decision, not a row:
{"attentionScore": 94,"riskTier": "extreme","alertLevel": "cluster","inventoryMatches": [{ "item": "CRT-D DTBA2D1", "matchType": "model", "confidence": "high" }],"recommendedAction": "act-immediately"}
Why teams switch from FDA search tools
| Question | FDA Database / openFDA | Typical recall feed | This actor |
|---|---|---|---|
| Was there a recall? | Yes | Yes | Yes |
| How dangerous is it? | No | No | Yes |
| How big is it (blast radius)? | No | No | Yes |
| Is it part of a recurring failure pattern? | No | No | Yes |
| Is the manufacturer deteriorating? | No | No | Yes |
| Does it affect my inventory? | No | No | Yes |
| What changed since yesterday? | No | Partial | Yes |
| What should I do? | No | No | Yes |
Everyone else gives you recall data. This actor gives you recall decisions. All deterministic -- no LLM, no API key.
What a raw FDA query returns vs what this returns
A raw openFDA query (or a generic recall feed) hands you fields to interpret yourself:
{"recalling_firm": "Medtronic, Inc.","classification": "Class I","status": "Ongoing","product_description": "Cardiac Resynchronization Therapy Defibrillator, Model DTBA2D1","reason_for_recall": "Firmware may cause an unexpected device reset, potentially resulting in loss of pacing therapy."}
This actor returns the same recall already scored, routed, and contextualised:
{"riskScore": 95, "riskTier": "extreme","attentionScore": 94,"blastRadius": { "unitsAffected": 45230, "distributionScope": "worldwide", "reachTier": "large" },"reasonCategory": "software","alertLevel": "cluster", "clusterId": "medtronic-inc-software", "clusterSize": 4,"recommendedAction": "act-immediately","summary": "Class I (critical) recall — Medtronic, Inc.: firmware may cause unexpected device reset… Initiated 2024-06-15; status Ongoing."}
You stop reading recall records and start working a ranked queue.
The four questions it answers
- Am I affected? Match recalls against your own device inventory and get a prioritized worklist (
inventory->actionQueue+exposureSummary). - Is this systemic or isolated? Cluster detection groups repeat firm + failure-mode recalls (
clusterId,largestActiveCluster). - Which manufacturer is getting riskier? Manufacturer profiles +
manufacturerHealth(supplier risk rating, with an all-firmsindustryPercentile) + a firm-wide MAUDE adverse-event trend rank suppliers by 12-month behaviour. - What changed since yesterday? Watchlist monitoring tags every recall NEW / ESCALATED / RISK_INCREASED / RESOLVED and surfaces newly-formed clusters.
Who uses this
- Hospital risk teams -- "Which devices in our inventory have active recalls?" -> upload
inventory, get a rankedactionQueue. - Procurement teams -- "Which manufacturers are becoming riskier?" ->
manufacturerHealth+industryPercentilerank suppliers by recall performance. - Compliance teams -- "What changed since our last review?" ->
watchlistNamesurfaces only NEW / ESCALATED / RESOLVED. - Device safety analysts -- "Which failure modes are increasing?" ->
reasonCategoryclusters +trendSignals. - AI agents -- "Give me structured recall decisions, not raw FDA data." -> every record carries
recommendedAction,riskTier, andattentionScoreto branch on.
Why this exists
The FDA already provides recall data. Regulatory, procurement, and hospital-risk teams don't need more data -- they need answers: which recalls matter, which suppliers are getting worse, what changed since yesterday, which devices affect them, and what action to take. This actor converts raw FDA recall records into operational intelligence. That is the difference between "we query openFDA" and "here is your worklist."
Four things it does
Inventory exposure -- upload your device inventory, get the affected recalls ranked into a worklist (exposureSummary + actionQueue).
Supplier risk -- rank manufacturers by 12-month recall performance, with a real all-firms percentile and an opt-in MAUDE adverse-event trend.
Recall monitoring -- a scheduled watchlistName run tells you only what changed since yesterday, including newly-forming clusters.
Executive intelligence -- outputMode: "executive" returns a decision-ready brief (headline risk, worsening suppliers, recommended actions) for directors and procurement leads.
Example executive brief
This is what outputMode: "executive" returns from thousands of FDA recall records in one call:
{"headlineRisk": "high","newCriticalRecalls": 11,"riskTrajectory": { "signal": "worsening", "reasons": ["Class I recalls up 18.2% year-over-year", "2 new failure-mode cluster(s) forming"] },"worseningManufacturers": ["Medtronic, Inc."],"recommendedActions": ["Review 12 active Class I recall(s) immediately.", "Reassess suppliers with worsening trend: Medtronic, Inc."]}
Every recall is also scored two ways -- riskScore (intrinsic danger) and attentionScore (how much you should look, given clusters + your inventory) -- so you can sort straight to "the 10 that matter," and routed with recommendedAction. The implementation details (risk model, watchlists, clusters, MAUDE signals, dashboards) follow below; the decisions above are what you actually consume.
What does FDA Medical Device Recall Search do?
FDA Medical Device Recall Search queries the U.S. Food and Drug Administration's openFDA device enforcement endpoint to retrieve detailed, structured data about medical device recalls. The FDA issues recalls when devices -- from pacemakers and insulin pumps to surgical robots and diagnostic imaging systems -- are found to be defective, mislabeled, or potentially harmful. Four output modes: records for individual triaged recalls, aggregation for top-N leaderboards (firms, product codes, countries, years), dashboard for a single compact digest, and executive for a curated decision brief.
You can search by keyword (matched across product descriptions and recall reasons), recalling company, recall severity classification (Class I/II/III), recall status (Ongoing/Completed/Terminated), U.S. state, and recall initiation date range. Results are always sorted newest first. Each record includes recall identification, severity, company details, product description, reason for recall, distribution scope, lot/serial code information, and four distinct dates covering the full recall lifecycle.
Unlike a raw API dump, every record arrives triaged and scored: a deterministic riskScore (0-100) and riskTier, a normalised severity, an isActive flag, a reasonCategory (failure mode), an exposureIndex (how long an active recall has been live and how widely distributed), a repeatSignal (is this a recurring firm + failure-mode issue), a recommendedAction decision scalar, and a one-line summary an agent can quote verbatim. A run-level summary row mirrors the headline numbers (active Class I count, risk-tier breakdown, recall clusters, top firms) so a downstream node never has to scan the dataset.
It is also a monitoring platform: set a watchlistName and the actor tracks recalls across scheduled runs, tagging each one NEW / ESCALATED / RISK_INCREASED / RESOLVED so you are alerted only on what changed. Opt into manufacturer profiles (a 12-month recall record per firm) and year-over-year trend signals, filter by risk tier / failure mode / active status, match recalls against your own device inventory, or switch to dashboard mode for a single compact digest object built for BI tools and AI agents.
Why use FDA Medical Device Recall Search on Apify?
- No API complexity -- The openFDA query syntax uses bracket-delimited date ranges,
+AND+joins, and quoted field searches. This actor builds the correct query from simple input fields. - Automatic pagination -- openFDA limits responses to 100 records per page with a 25,000 skip ceiling. The actor handles all pagination transparently, fetching up to 5,000 results across multiple API calls.
- Clean date formatting -- Raw openFDA dates (YYYYMMDD) are converted to standard YYYY-MM-DD format in every output record.
- Schedule for monitoring -- Run daily or weekly on Apify to catch new device recalls as they are published, with webhook alerts to Slack, email, or any endpoint.
- No API key required -- The openFDA API is completely free and open. The only cost is minimal Apify platform compute time.

Key features
- Three output modes -- Records mode returns one triaged row per recall. Aggregation mode returns top-N count buckets so you can answer "which firms had the most recalls last year?" in a single call. Dashboard mode returns one compact digest object (headline risk, active counts, risk-tier breakdown, clusters, top firms, trends) for Power BI / Grafana / Looker / Dify / n8n.
- Aggregation grouping fields -- group by
recalling_firm.exact,product_code.exact, orevent_date_initiated.year. Each bucket includes rank, count, share of total, and the filters that produced it. - Multi-field keyword search -- Keywords are matched across both
product_descriptionandreason_for_recallusing OR logic, so you catch recalls whether the term appears in the device name or the defect explanation. - Six combinable filters -- Keyword, recalling firm, classification, status, state, and date range can be used in any combination.
- Date range filtering -- Filter by recall initiation date (the date the firm started the recall), not report date. This gives you the actual timeline of when recalls began.
- Structured output with a triage layer -- Every record carries the raw FDA fields (recall number, event ID, classification, status, company, product, quantity, reason, distribution, notification, code info, four dates) plus a deterministic intelligence block:
severity,isActive,reasonCategory,recommendedAction, and a quotablesummary. - Deterministic risk scoring -- Every recall gets a
riskScore(0-100) andriskTier(extreme / high / moderate / low) from a transparent weighted model (FDA class + active status + worldwide distribution + failure mode + harm language). Sort or filter on it directly — no interpretation needed. - Attention score (recall-fatigue cure) --
attentionScore(0-100) layers operational relevance — does it hit your inventory, is it part of a cluster, is it active — on top of intrinsic risk, withattentionReasons. Sort by it to get "show me the 10 that matter" instead of drowning in alerts. - Inventory exposure worklist -- With an
inventorylist, the run returns anexposureSummary(affectedDevices/highRiskAffected/activeAffected/manufacturersAffected) and a prioritizedactionQueue— upload inventory, get a worklist. - Manufacturer health + supplier risk -- Firm profiles carry a decomposed
manufacturerHealth(score, trend, within-cohortrankPercentile, Class I weight, closure performance, repeat-failure weight) and, opt-in, a firm-wide MAUDE adverse-event trend (adverseEventSignal). Answers "should we keep buying from this company?". - Executive mode --
outputMode: "executive"returns one curated brief — headline risk,riskTrajectory, top threats, affected and worsening manufacturers, recommended actions — for directors and procurement leads, not analysts. - Recall triage intelligence --
severitynormalises the FDA class,reasonCategoryclassifies the failure mode (software, sterility, mechanical, electrical, labeling, …),exposureIndexflags long-running, widely-distributed active recalls,repeatSignalflags recurring firm + failure-mode issues, andrecommendedAction(act-immediately/assess-exposure/monitor/informational) is a stable decision scalar that Dify / Zapier / n8n nodes branch on without parsing prose. - Manufacturer profiles -- Opt in with
includeFirmProfilesto get akind: "firm-profile"record per top firm: 12-month total / Class I / active recall counts, ariskTrend(worsening / improving / stable), and the failure modes they repeat. - Year-over-year trends -- Opt in with
includeTrendAnalysisfortrendSignals(total and Class I recall counts, last 365 days vs prior 365 days) in the summary / dashboard. - Filters that drop from billing --
activeOnly,minimumRiskScore,riskTierFilter,reasonCategoryFilter,country, anddistributionContainsnarrow the output; filtered-out records are excluded from both the dataset and per-record charges. - Device inventory matching -- Pass an
inventorylist of device names / models / lot codes; each recall is tagged with the items it matches, with a deterministic token match (no AI). - Run summary row + KV mirror -- A final
kind: "summary"record carries coverage, class/status/severity/risk-tier/failure-mode breakdowns, active and active-Class-I counts, recall clusters, top firms (by count and by summed risk), and date range. The same digest is pinned to theSUMMARYkey-value store key for agents and MCP clients. - Watchlist change tracking -- Set
watchlistNameto remember recalls across runs. Each record then carries atemporalSignals.changeFlag(NEW, ESCALATED, RISK_INCREASED, RESOLVED, STATUS_CHANGED, REINSTATED, UNCHANGED) plus the previous status / class / risk score, so scheduled monitoring surfaces only what changed. - Sorted by recency -- Results always come back with the most recent recalls first (
recall_initiation_date:desc).
How to use FDA Medical Device Recall Search
- Navigate to the FDA Medical Device Recall Search actor page on Apify.
- Click Try for free to open the actor in Apify Console.
- Enter your search parameters. At minimum, provide a keyword like "pacemaker" or a company name like "Medtronic". You can also leave all filters blank to retrieve the most recent recalls across all categories.
- Set Max Results to control how many records you want (default 100, maximum 5,000).
- Click Start to run the actor.
- When the run finishes, view results in the Dataset tab. Export as JSON, CSV, Excel, or access via the Apify API.
Input parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
outputMode | select | No | records | records (one triaged row per recall), aggregation (top-N buckets), dashboard (single compact digest), or executive (curated decision brief). |
aggregateBy | select | No | recalling_firm.exact | When outputMode=aggregation: recalling_firm.exact, product_code.exact, event_date_initiated.year, or country. |
keyword | string | No | "pacemaker" (prefill) | Search term matched against product descriptions and recall reasons. Examples: "pacemaker", "insulin pump", "hip implant", "ventilator". |
recallingFirm | string | No | -- | Filter by company name. Examples: "Medtronic", "Abbott", "Philips", "Baxter". |
classification | select | No | -- | Recall severity: "Class I" (most serious), "Class II" (moderate), or "Class III" (least serious). |
status | select | No | -- | Recall status: "Ongoing", "Completed", or "Terminated". |
state | string | No | -- | Two-letter U.S. state code where the recalling firm is located (e.g., CA, MN, MA). Automatically uppercased. |
dateFrom | string | No | -- | Start of recall initiation date range (YYYY-MM-DD format). |
dateTo | string | No | -- | End of recall initiation date range (YYYY-MM-DD format). |
maxResults | integer | No | 100 | Maximum recalls (records mode) or buckets (aggregation mode) to return (1--5,000). |
watchlistName | string | No | -- | Records / dashboard mode. Set a name to enable cross-run change tracking (each name keeps its own independent history). Blank = stateless one-off search. |
country | string | No | -- | Filter by recalling firm's country (server-side, e.g. "United States"). |
activeOnly | boolean | No | false | Emit only Ongoing (unresolved) recalls. |
minimumRiskScore | integer | No | -- | Drop recalls below this 0-100 risk score from output and billing. |
riskTierFilter | array | No | -- | Keep only these risk tiers: extreme, high, moderate, low. |
reasonCategoryFilter | array | No | -- | Keep only these failure modes (e.g. software, sterility). |
distributionContains | string | No | -- | Keep only recalls whose distribution pattern contains this substring (e.g. "worldwide"). |
inventory | array | No | -- | Records mode: device names / models / lot codes to match against recalls (inventoryMatches per record). |
includeFirmProfiles | boolean | No | false | Emit a 12-month manufacturer profile per top firm (a few extra openFDA count queries). |
includeTrendAnalysis | boolean | No | false | Add year-over-year trendSignals to the summary / dashboard. |
includeAdverseEvents | boolean | No | false | With manufacturer profiles, add a firm-wide MAUDE adverse-event trend (adverseEventSignal) per profile. |
Templates (copy-paste use cases)
Hospital inventory monitoring -- which of your devices have active recalls, ranked into a worklist:
{"inventory": ["CRT-D DTBA2D1", "Alaris 8100 infusion pump", "Synchromed II"],"activeOnly": true,"watchlistName": "our-inventory","maxResults": 1000}
Procurement supplier risk review -- rank a manufacturer's recall behaviour with peer percentile and adverse-event trend:
{"recallingFirm": "Medtronic","includeFirmProfiles": true,"includeAdverseEvents": true,"includeTrendAnalysis": true,"outputMode": "executive"}
Pacemaker recall watchlist -- scheduled cohort monitor, alert only on what changed:
{"keyword": "pacemaker","watchlistName": "pacemakers","includeTrendAnalysis": true,"maxResults": 500}
Infusion pump safety monitoring -- Class I + active only, executive brief:
{"keyword": "infusion pump","classification": "Class I","status": "Ongoing","outputMode": "executive"}
Input examples
Basic keyword search (pacemaker):
{"keyword": "pacemaker","maxResults": 100}
Company + Class I recalls:
{"recallingFirm": "Medtronic","classification": "Class I","maxResults": 500}
Date range + state filter:
{"keyword": "insulin pump","state": "CA","dateFrom": "2024-01-01","dateTo": "2024-12-31","maxResults": 200}
All recent recalls (no filters):
{"maxResults": 100}
Aggregation mode -- top recalling firms for Class I recalls in 2024:
{"outputMode": "aggregation","aggregateBy": "recalling_firm.exact","classification": "Class I","dateFrom": "2024-01-01","dateTo": "2024-12-31","maxResults": 25}
Aggregation mode -- year-over-year recall trend for Medtronic:
{"outputMode": "aggregation","aggregateBy": "event_date_initiated.year","recallingFirm": "Medtronic","maxResults": 20}
Tips for best results
- Be specific with keywords. Terms like "insulin pump" or "cardiac defibrillator" return more targeted results than generic terms like "device" or "medical".
- Combine filters for precision. Use keyword plus classification together to find, for example, all Class I recalls related to surgical robots.
- Date ranges use recall initiation date. This is the date the firm initiated the recall -- not the date FDA classified it or the date it was reported to the FDA.
- State codes are auto-uppercased. You can enter "ca" or "CA" -- both work.
- Leave all filters blank to get the most recent recalls across all device categories, useful for general monitoring dashboards.
- Use date ranges for trend analysis. Split long time periods into smaller windows if you need more than 5,000 results for a given query.
Output example

Every row carries a kind discriminator: "record" for individual recalls, "aggregation" for count buckets. Filter kind === "aggregation" downstream to isolate leaderboard rows.
Records mode
{"kind": "record","recallNumber": "Z-0839-2024","eventId": "92134","classification": "Class I","status": "Ongoing","recallingFirm": "Medtronic, Inc.","city": "Minneapolis","state": "MN","country": "United States","productDescription": "Cardiac Resynchronization Therapy Defibrillator (CRT-D), Model DTBA2D1, used for the treatment of heart failure in patients who also have ventricular arrhythmias.","productQuantity": "45,230","reasonForRecall": "The firmware in the device may cause an unexpected device reset during normal operation, potentially resulting in loss of pacing therapy.","distributionPattern": "Worldwide Distribution -- US (nationwide) and international including EU, Canada, Japan, Australia.","voluntaryMandated": "Voluntary: Firm Initiated","initialNotification": "Letter","codeInfo": "Serial numbers: PXR1000001 through PXR1045230, manufactured between January 2022 and March 2024.","recallDate": "2024-06-15","classificationDate": "2024-07-02","reportDate": "2024-06-28","terminationDate": null,"severity": "critical","isActive": true,"reasonCategory": "software","riskScore": 95,"riskTier": "extreme","exposureIndex": { "level": "high", "daysActive": 540, "worldwide": true },"repeatSignal": { "isRepeatIssue": true, "occurrencesInResultSet": 4, "category": "software" },"recallDurationDays": null,"closureSpeed": null,"alertLevel": "cluster","clusterId": "medtronic-inc-software","clusterSize": 4,"clusterType": "firm_failure_mode","blastRadius": { "unitsAffected": 45230, "distributionScope": "worldwide", "reachTier": "large" },"attentionScore": 92,"attentionReasons": ["extreme intrinsic risk", "part of a recall cluster", "recall is active"],"recommendedAction": "act-immediately","summary": "Class I (critical) recall — Medtronic, Inc.: The firmware in the device may cause an unexpected device reset during normal operation, potentially resulting in loss of pacing therapy. Initiated 2024-06-15; status Ongoing.","extractedAt": "2025-01-15T14:32:08.123Z"}
When watchlistName is set, each record additionally carries a temporalSignals block:
{"temporalSignals": {"changeFlag": "ESCALATED","previousStatus": "Ongoing","previousClassification": "Class II","firstSeenAt": "2026-05-01T09:00:00.000Z","runsSeen": 3}}
Summary row
The final record in every records-mode run is a kind: "summary" digest (also mirrored to the SUMMARY key-value store key):
{"kind": "summary","coverage": { "totalMatching": 3510, "returned": 100, "truncated": true },"classBreakdown": { "Class I": 18, "Class II": 71, "Class III": 11 },"statusBreakdown": { "Ongoing": 42, "Terminated": 58 },"severityBreakdown": { "critical": 18, "moderate": 71, "low": 11, "unknown": 0 },"reasonCategoryBreakdown": { "software": 22, "mechanical": 19, "labeling": 14, "sterility": 9, "other": 36 },"activeCount": 42,"criticalActiveCount": 7,"dominantRisk": "critical","topFirms": [{ "firm": "Medtronic, Inc.", "count": 12 }, { "firm": "Abbott", "count": 8 }],"dateRange": { "earliest": "2026-01-04", "latest": "2026-04-22" },"watchlist": null,"summary": "100 device recall(s) returned of 3,510 matching. 42 active, 7 active Class I (critical). Top firm: Medtronic, Inc. (12).","extractedAt": "2026-05-08T10:00:00.000Z"}
Aggregation mode
Top recalling firms for Class I recalls in 2024 (aggregateBy: "recalling_firm.exact"):
[{ "kind": "aggregation", "aggregateBy": "recalling_firm.exact", "rank": 1, "term": "Medtronic, Inc.", "count": 142, "share": 0.0834, "totalMatching": 1703, "queryFilters": { "keyword": null, "recallingFirm": null, "classification": "Class I", "status": null, "state": null, "dateFrom": "2024-01-01", "dateTo": "2024-12-31" }, "extractedAt": "2026-05-08T10:00:00.000Z" },{ "kind": "aggregation", "aggregateBy": "recalling_firm.exact", "rank": 2, "term": "Baxter Healthcare Corporation", "count": 98, "share": 0.0575, "totalMatching": 1703, "queryFilters": { "keyword": null, "recallingFirm": null, "classification": "Class I", "status": null, "state": null, "dateFrom": "2024-01-01", "dateTo": "2024-12-31" }, "extractedAt": "2026-05-08T10:00:00.000Z" }]
Year-over-year recall trend for Medtronic (aggregateBy: "event_date_initiated.year"):
[{ "kind": "aggregation", "aggregateBy": "event_date_initiated.year", "rank": 1, "term": "2024", "count": 87, "share": 0.0412, "totalMatching": 2113, "queryFilters": { "keyword": null, "recallingFirm": "Medtronic", "classification": null, "status": null, "state": null, "dateFrom": null, "dateTo": null }, "extractedAt": "2026-05-08T10:00:00.000Z" },{ "kind": "aggregation", "aggregateBy": "event_date_initiated.year", "rank": 2, "term": "2023", "count": 74, "share": 0.0350, "totalMatching": 2113, "queryFilters": { "keyword": null, "recallingFirm": "Medtronic", "classification": null, "status": null, "state": null, "dateFrom": null, "dateTo": null }, "extractedAt": "2026-05-08T10:00:00.000Z" }]
Output fields reference
| Field | Type | Description |
|---|---|---|
recallNumber | string | Unique FDA recall identification number (e.g., "Z-0839-2024") |
eventId | string | FDA event ID grouping related recall records |
classification | string | Severity level: "Class I", "Class II", or "Class III" |
status | string | Current recall status: "Ongoing", "Completed", or "Terminated" |
recallingFirm | string | Name of the company responsible for the recall |
city | string | City where the recalling firm is located |
state | string | U.S. state where the recalling firm is located (two-letter code) |
country | string | Country where the recalling firm is located |
productDescription | string | Detailed description of the recalled medical device |
productQuantity | string | Number or description of units affected |
reasonForRecall | string | The specific defect or issue that triggered the recall |
distributionPattern | string | Geographic scope of where the device was distributed |
voluntaryMandated | string | Whether the recall was voluntary or FDA-mandated |
initialNotification | string | How the firm initially notified customers (e.g., "Letter", "Press Release") |
codeInfo | string | Lot numbers, serial numbers, or other identifying codes for affected units |
recallDate | string | Date the firm initiated the recall (YYYY-MM-DD) |
classificationDate | string | Date the FDA classified the recall severity (YYYY-MM-DD) |
reportDate | string | Date the recall was reported to the FDA (YYYY-MM-DD) |
terminationDate | string or null | Date the recall was terminated (YYYY-MM-DD), or null if still active |
severity | string | Normalised severity: critical (Class I), moderate (Class II), low (Class III), unknown |
isActive | boolean | true when status is Ongoing (recall unresolved) |
reasonCategory | string | Failure-mode category from the recall text: software, sterility, contamination, biocompatibility, electrical, mechanical, measurement, material, packaging, labeling, manufacturing, design, other |
riskScore | integer | Deterministic 0-100 risk score (class + active + worldwide + failure mode + harm language) |
riskTier | string | extreme (≥80), high (≥60), moderate (≥35), low (<35) |
exposureIndex | object | { level (high/medium/low/none), daysActive, worldwide } — live exposure of an unresolved recall |
repeatSignal | object | { isRepeatIssue, occurrencesInResultSet, category } — recurrence of this firm + failure mode within this query's result set (varies with maxResults; for stable firm history use includeFirmProfiles) |
recallDurationDays | integer or null | Days from initiation to termination; null while active |
closureSpeed | string or null | fast (<90d) / average (90-270d) / slow (>270d); null while active |
alertLevel | string | cluster (in a firm + failure-mode cluster) / elevated (extreme/high tier) / normal |
blastRadius | object | "How big is this problem?" — { unitsAffected (parsed, null if unclear), distributionScope, reachTier } |
clusterId | string or null | Stable id of the firm + failure-mode cluster (3+ in the result set); null when not clustered |
clusterSize | integer or null | Recalls in this recall's cluster |
clusterType | string or null | firm_failure_mode when clustered |
attentionScore | integer | Contextual triage 0-100 (risk + cluster + inventory + active). Sort by this to cut alert fatigue |
attentionReasons | array | Why the attention score is what it is |
inventoryMatches | array or absent | Present only when inventory is set: [{ item, matchType (model/name/generic), confidence (high/medium/low) }] |
inventoryConfidence | string or absent | Highest match confidence among this recall's inventory matches |
recommendedAction | string | Decision scalar: act-immediately, assess-exposure, monitor, informational |
summary | string | Quotable one-line summary (≤280 chars) for LLM/agent use |
temporalSignals | object or absent | Present only when watchlistName is set: { changeFlag, previousStatus, previousClassification, firstSeenAt, runsSeen } |
extractedAt | string | ISO 8601 timestamp of when the data was extracted |
kind | string | "record" for recalls, "summary" for the run digest, "aggregation" for leaderboard rows |
Output fields -- aggregation mode
| Field | Type | Description |
|---|---|---|
kind | string | Always "aggregation" in aggregation mode |
aggregateBy | string | Field used for grouping (e.g., "recalling_firm.exact", "pathway") |
rank | integer | 1-based bucket position (sorted by count descending) |
term | string | Bucket value (e.g., a firm name, a year "2024", or "PMA"/"non-PMA") |
count | integer | Number of recalls in this bucket |
share | number | count / totalMatching (0--1) |
totalMatching | integer | Total recalls matching the query filters |
queryFilters | object | Echo of the filters that produced this aggregation, for traceability |
extractedAt | string | ISO 8601 timestamp of when the aggregation was computed |
Recall triage and watchlist intelligence
The actor adds a deterministic decision layer on top of the raw FDA fields. Nothing here uses an LLM or randomness — the same recall always produces the same severity, category, and action, so the output is reproducible and auditable.
Per-record triage
| Field | How it is derived | What to branch on |
|---|---|---|
attentionScore | riskScore + cluster + inventory hit + active | Sort by this for "the N that matter to me"; cuts recall fatigue |
riskScore | Weighted model (see below) | Sort the whole dataset by intrinsic risk; threshold with minimumRiskScore |
riskTier | riskScore band | extreme / high / moderate / low badge for UI + Slack |
severity | FDA class → critical (I) / moderate (II) / low (III) | Filter or sort by class without parsing "Class I/II/III" strings |
isActive | status === "Ongoing" | Surface only unresolved recalls |
reasonCategory | Keyword match over reasonForRecall + productDescription against a fixed failure-mode lexicon | "Show me every software / sterility / mechanical recall" |
exposureIndex | active status + days since recall + worldwide distribution | Find long-running, widely-distributed open recalls |
repeatSignal | firm + failure-mode recurrence in the result set | Spot chronic engineering failures |
blastRadius | units affected + distribution scope | "How big is this problem?" — sort by reachTier |
alertLevel | cluster membership + risk tier | cluster / elevated / normal one-glance badge |
clusterId / clusterSize | 3+ same firm + failure mode in the set | Tell a systemic problem from an isolated recall |
recallDurationDays / closureSpeed | termination date − recall date | Spot firms that close recalls slowly (slow >270d) |
recommendedAction | severity × isActive | Route the record: act-immediately, assess-exposure, monitor, informational |
summary | Templated one-liner | Quote directly in an LLM prompt, Slack message, or email |
Risk score model (deterministic, capped at 100): Class I +40 / Class II +15 / Class III +5; active (Ongoing) +20; worldwide/nationwide distribution +10; sterility or contamination failure +15; software / electrical / mechanical failure +5; explicit harm language (death, injury, life-threatening, loss of therapy) +20. Tiers: extreme ≥80, high ≥60, moderate ≥35, low <35.
recommendedAction mapping: a critical + active recall is act-immediately; critical but resolved is assess-exposure; moderate + active is assess-exposure; moderate + resolved is monitor; low is monitor (active) or informational (resolved).
Watchlist mode (cross-run change tracking)
Set watchlistName to turn a one-off search into a monitored feed. The actor stores a snapshot of every recall it sees (keyed by the stable FDA recallNumber) in a named key-value store unique to that watchlist name, then diffs the current run against the last one:
- NEW -- not seen in any prior run under this name.
- ESCALATED -- the recall was re-classified to a more severe class (e.g. Class II → Class I).
- RISK_INCREASED -- the
riskScorerose by 10+ points since last run without a class change (e.g. it went active, or distribution widened). - RESOLVED -- was Ongoing, now Terminated/Completed.
- REINSTATED -- was Terminated, now Ongoing again.
- STATUS_CHANGED -- status changed in some other way.
- UNCHANGED -- identical to last run.
The first run under a new name tags everything NEW (logged explicitly). Schedule the same watchlistName daily or weekly and filter temporalSignals.changeFlag in (NEW, ESCALATED, RISK_INCREASED, REINSTATED) to alert only on what actually changed. Each record also carries previousStatus, previousClassification, and previousRiskScore. Each watchlist name keeps its own independent, bounded history (most recent 25,000 recalls).
Monitor a device cohort, not individual recalls. Set a keyword (e.g. "infusion pump", "pacemaker", "imaging system") plus a watchlistName and includeTrendAnalysis, and a scheduled run becomes a cohort monitor: the summary gives the cohort's active and Class I counts, trendSignals shows whether that category's recall rate is rising, and the watchlist surfaces only what changed. One actor, one schedule, per device family.
Run summary record
Every records-mode run ends with one kind: "summary" row carrying coverage, the class/status/severity/risk-tier/failure-mode breakdowns, active and active-Class-I counts, recall clusters, top firms (by count and by summed risk), and the date range of the returned set. The identical object is written to the SUMMARY key-value store key, so an agent or MCP client can read the run's headline risk picture with a single KV fetch instead of paging the dataset.
Dashboard mode
Set outputMode: "dashboard" to skip the per-recall rows and emit a single compact kind: "dashboard" digest, also pinned to the SUMMARY KV key:
{"kind": "dashboard","headlineRisk": "extreme","totalReturned": 200,"activeRecalls": 84,"classIActive": 12,"riskTierBreakdown": { "extreme": 14, "high": 31, "moderate": 96, "low": 59 },"reasonCategoryBreakdown": { "software": 41, "mechanical": 33, "sterility": 12, "other": 114 },"topFirms": [{ "firm": "Medtronic, Inc.", "count": 18 }],"riskWeightedTopFirms": [{ "firm": "Medtronic, Inc.", "riskTotal": 1240, "riskAverage": 69 }],"clusters": [{ "firm": "Medtronic, Inc.", "category": "software", "count": 6 }],"newClusters": [{ "firm": "Abbott", "category": "electrical", "count": 3 }],"mostDangerousFirm": "Medtronic, Inc. (risk 1240)","mostCommonFailureMode": "software","largestActiveCluster": "Medtronic, Inc. — software (6)","largestRiskIncrease": "New cluster: Abbott — electrical (3)","newThisRun": 11,"escalatedThisRun": 2,"riskIncreasedThisRun": 4,"trendSignals": { "classITrendPct": 18.2, "totalTrendPct": 6.4, "window": "last 365 days vs prior 365 days", "note": "Total recalls: 3120 → 3320. Class I: 412 → 487." }}
It is the ideal shape for a BI tile, a Dify/n8n variable, or an exec alert: one object, the four "15-second" answers (mostDangerousFirm, mostCommonFailureMode, largestActiveCluster, largestRiskIncrease), all the headline numbers, no dataset paging. riskWeightedTopFirms carries both riskTotal and riskAverage so a firm with many low-risk recalls doesn't outrank one with fewer severe ones. trendSignals is populated when includeTrendAnalysis is set; the watchlist deltas (newThisRun, escalatedThisRun, riskIncreasedThisRun, newClusters) are populated when watchlistName is set.
Executive mode
Set outputMode: "executive" for a single curated kind: "executive" brief aimed at directors and procurement leads — not analysts. It auto-builds manufacturer profiles to surface worsening suppliers:
{"kind": "executive","headlineRisk": "high","activeRecalls": 84,"classIActive": 12,"riskTrajectory": { "signal": "worsening", "reasons": ["Class I recalls up 18.2% year-over-year", "2 new failure-mode cluster(s) forming"] },"topThreats": [{ "device": "Cardiac Resynchronization Therapy Defibrillator", "recallNumber": "Z-0839-2024", "recallingFirm": "Medtronic, Inc.", "priority": "urgent", "attentionScore": 92, "riskTier": "extreme", "recommendedAction": "act-immediately", "matchedInventory": [] }],"affectedManufacturers": [{ "firm": "Medtronic, Inc.", "count": 18 }],"worseningManufacturers": ["Medtronic, Inc."],"newCriticalRecalls": 11,"exposureSummary": null,"recommendedActions": ["Review 12 active Class I recall(s) immediately.", "Reassess suppliers with worsening trend: Medtronic, Inc."]}
riskTrajectory is a deterministic "is this getting worse?" read built from trends + new clusters + risk movement; recommendedActions are templated next steps (no LLM). Pair with includeTrendAnalysis for the trajectory and watchlistName for newCriticalRecalls.
Manufacturer profiles
Set includeFirmProfiles: true to emit a kind: "firm-profile" record for each of the top firms in the result set, built from openFDA count queries:
{"kind": "firm-profile","firm": "Medtronic, Inc.","totalRecalls12m": 42,"classIRecalls12m": 7,"activeRecalls": 9,"riskTrend": "worsening","manufacturerScore": 62,"manufacturerTier": "elevated","manufacturerHealth": { "score": 62, "trend": "worsening", "trend3y": "worsening", "rankPercentile": 88, "industryPercentile": 99, "confidence": "high", "classIWeight": 28, "closurePerformance": 34, "repeatFailureWeight": 10 },"adverseEventSignal": { "manufacturerLevel": true, "adverseEventsRecent": 4120, "adverseEventsPrior": 3110, "trendPct": 32.5, "signalStrength": "rising", "window": "two 180-day windows ending 90 days ago (MAUDE reporting lag buffer)", "note": "Firm-wide MAUDE reports: 3110 → 4120. Manufacturer-level, not device-specific." },"repeatFailureCategories": ["software", "electrical"],"inResultSet": 18}
This answers the question procurement and hospital risk teams actually ask — "should I trust this manufacturer?" — not just "was this device recalled?". manufacturerScore (0-100) + manufacturerTier let you rank firms; manufacturerHealth decomposes the score so the number is auditable: trend (6mo) and trend3y (3-year horizon), rankPercentile (vs the firms profiled this run), industryPercentile (the firm's standing by 12-month recall volume among all recalling firms, a real peer comparison, not a within-run one), a confidence (high / medium / low, from how many recalls the score rests on, so a 99th-percentile ranking off 2 recalls reads low not signal), classIWeight, closurePerformance (% of closed recalls that closed slowly), and repeatFailureWeight. With includeAdverseEvents, adverseEventSignal adds a firm-wide MAUDE adverse-event trend — manufacturer-level, not device-specific (enforcement records carry no reliable device join key), and lag-buffered because MAUDE data publishes ~3-6 months behind.
Device inventory matching
Pass an inventory list of device names, models, or lot/serial codes you own. Each returned recall is tagged with the inventory items it matches (inventoryMatches), with a matchType (model / name / generic) and confidence (high / medium / low) per match and a top-level inventoryConfidence for the strongest. The match is deterministic token matching against the product description, code info, and firm name — no AI.
The run also returns a worklist: an exposureSummary ({ affectedDevices, highRiskAffected, activeAffected, manufacturersAffected }) and a prioritized actionQueue of the matched recalls sorted by attention score, each with a priority (urgent / high / medium / low). Upload inventory → get a ranked list of what to act on. Both appear in the summary, dashboard, and executive records.
Cluster detection
When 3+ recalls in the result set share the same firm and failure mode, they form a cluster. Each clustered record carries clusterId, clusterSize, clusterType: "firm_failure_mode", and alertLevel: "cluster"; the summary and dashboard list every cluster (clusters). This is the difference between one recall = an issue and six recalls = a systemic problem. With watchlistName set, clusters that did not exist on the previous run are reported as newClusters — the alert a quality team wants the moment a manufacturer's failure mode starts repeating.
How it works

Input (keyword, recallingFirm, classification, status, state, dateFrom, dateTo, watchlistName)|v+-----------------------------------------------------------+| Query Builder || - Joins all filter clauses with +AND+ || - Keywords: OR across product_description || and reason_for_recall || - Dates: strip dashes, wrap in [FROM+TO+TO] || - Special chars (+, &, |, parens) stripped from keywords |+----------------------------+------------------------------+|v+-----------------------------------------------------------+| Paginated Fetch || api.fda.gov/device/enforcement.json || ?limit=100&skip=N&sort=recall_initiation_date:desc || &search=<query> || || - 100 results per page (openFDA maximum) || - Stops at maxResults, end of data, or skip >= 25000 || - First-page 404 = no results found || - Later-page 404 = end of available data |+----------------------------+------------------------------+|v+-----------------------------------------------------------+| Transform + Triage || - Raw FDA fields + dates YYYYMMDD -> YYYY-MM-DD || - severity / isActive / reasonCategory derived || - recommendedAction decision scalar || - summary one-liner || - temporalSignals (when watchlistName set) |+----------------------------+------------------------------+|v+-----------------------------------------------------------+| Output & Summary || - Stream each triaged record to the dataset || - Diff against prior run (watchlist mode) || - Emit a kind:"summary" digest row || - Mirror the digest to the SUMMARY KV key |+-----------------------------------------------------------+
openFDA query construction
The actor maps each input field to an openFDA query fragment, then joins all fragments with +AND+:
| Input field | Query fragment | Example |
|---|---|---|
keyword | (product_description:"K"+reason_for_recall:"K") | (product_description:"pacemaker"+reason_for_recall:"pacemaker") |
recallingFirm | recalling_firm:"FIRM" | recalling_firm:"Medtronic" |
classification | classification:"CLASS" | classification:"Class I" |
status | status:"STATUS" | status:"Ongoing" |
state | state:"ST" (uppercased) | state:"CA" |
dateFrom / dateTo | recall_initiation_date:[FROM+TO+TO] | recall_initiation_date:[20240101+TO+20241231] |
The keyword field uses OR logic (the + between quoted field searches inside parentheses acts as OR in openFDA syntax). Special characters (+, &, |, (, )) in keyword input are stripped before querying to prevent malformed API calls.
Date handling
Input dates in YYYY-MM-DD format have their dashes stripped to produce the YYYYMMDD format required by the openFDA API. For example, an input of "2024-01-15" becomes 20240115 in the query. If only dateFrom is specified, the range extends to 20991231. If only dateTo is specified, the range starts from 19000101. The formatDate() function reverses this for output, converting raw YYYYMMDD responses back to YYYY-MM-DD using substring slicing.
Skip-based pagination and the 25,000 limit
The openFDA API uses skip-based pagination (not cursor-based). Each request specifies a skip offset and a limit (max 100). The actor increments skip by the number of results received after each page. Pagination stops when any of three conditions are met: the total number of collected results reaches maxResults, a page returns fewer results than requested (end of data), or skip reaches 25,000 (the hard ceiling imposed by the openFDA API). The page size is also optimized on the final page: Math.min(100, maxResults - collected) to avoid over-fetching.
404 handling
The openFDA API returns HTTP 404 when no records match a query -- not a 200 with an empty array. The actor distinguishes between two cases: if the 404 occurs on the first page (no results collected yet), it means the search matched nothing and outputs a diagnostic message. If the 404 occurs on a subsequent page, it simply means pagination has reached the end of available data, and the actor stops fetching.
Recall classification levels
FDA classifies every device recall into one of three severity levels based on the potential health risk:
- Class I: Most serious. The device could cause serious adverse health consequences or death.
- Class II: Moderate. The device may cause temporary or medically reversible adverse health consequences, or the probability of serious harm is remote.
- Class III: Least serious. The device is unlikely to cause adverse health consequences but still violates FDA regulations.
Understanding the three date fields
Each recall record contains three (sometimes four) dates that represent different milestones in the recall lifecycle:
| Date field | Meaning |
|---|---|
recallDate | The date the recalling firm initiated the recall. This is the primary date used for sorting and filtering. |
reportDate | The date the recall was reported to the FDA. Typically the same day or shortly after the recall initiation date. |
classificationDate | The date the FDA officially classified the recall severity (Class I, II, or III). This is unique to the device endpoint and provides insight into how quickly the FDA assessed severity. It often comes days or weeks after the recall initiation. |
terminationDate | The date the recall was terminated (closed). This field is null for ongoing recalls and only populated when the recall has been completed and formally terminated. |
How much does it cost to run?
| Scenario | Records | API calls | Approx. time | Est. cost |
|---|---|---|---|---|
| Quick keyword search | 100 | 1 | ~5 sec | ~$0.002 |
| Company monitoring | 200--500 | 2--5 | ~10 sec | ~$0.005 |
| Date range trend analysis | 1,000 | 10 | ~30 sec | ~$0.008 |
| Maximum extraction | 5,000 | 50 | ~90 sec | ~$0.02 |
The openFDA API is completely free with no API key required. Apify's free tier includes $5 of monthly platform credits, enough for hundreds of runs of this actor.
Limitations
- 25,000 skip ceiling -- The openFDA API stops returning results after a skip offset of 25,000. For very large result sets, use date range filters to split queries into smaller time windows.
- 5,000 result cap -- The actor limits output to 5,000 records per run for practical performance.
- Keyword searches three fields -- Keywords match
product_description,reason_for_recall, andcode_info(so model and lot numbers are searchable). Matching is phrase-based, not fuzzy; openFDA has no fuzzy-search operator. - State filter is firm location -- The
statefilter matches where the recalling firm is headquartered, not where the device was distributed. Check thedistributionPatternoutput field for geographic distribution scope. - Date format required -- Dates must be entered in YYYY-MM-DD format. Other formats will produce incorrect API queries.
- Device recalls only -- This actor covers the
/device/enforcement.jsonendpoint. For drugs, food, or other FDA data, use the corresponding specialized actors listed in the Related Actors section.
Responsible use
- A recall does not always mean a device is dangerous. Class III recalls address regulatory violations that are unlikely to cause harm. Always check the classification and reason fields for context.
- When publishing or sharing recall data, provide appropriate context about recall severity and status.
- Consult healthcare professionals and the FDA directly for clinical decisions.
- Follow the openFDA Terms of Service when using the data.
FDA recall classification reference
| Class | Severity | Description |
|---|---|---|
| Class I | Most serious | Could cause serious health problems or death |
| Class II | Moderate | May cause temporary or reversible health problems |
| Class III | Least serious | Unlikely to cause adverse health effects |
Programmatic access
Python:
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("ryanclinton/fda-device-recalls").call(run_input={"keyword": "pacemaker","classification": "Class I","maxResults": 200,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(f"[{item['classification']}] {item['recallingFirm']}: {item['reasonForRecall'][:80]}")print(f" Recall #{item['recallNumber']} | Date: {item['recallDate']} | Status: {item['status']}")
JavaScript:
import { ApifyClient } from "apify-client";const client = new ApifyClient({ token: "YOUR_API_TOKEN" });const run = await client.actor("ryanclinton/fda-device-recalls").call({keyword: "pacemaker",classification: "Class I",maxResults: 200,});const { items } = await client.dataset(run.defaultDatasetId).listItems();const classI = items.filter((r) => r.classification === "Class I");console.log(`Found ${classI.length} Class I pacemaker recalls`);
cURL:
# Start a runcurl "https://api.apify.com/v2/acts/ryanclinton~fda-device-recalls/runs" \-X POST \-H "Content-Type: application/json" \-H "Authorization: Bearer YOUR_API_TOKEN" \-d '{"keyword": "pacemaker","classification": "Class I","maxResults": 200}'# Fetch results (after run completes)curl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=json" \-H "Authorization: Bearer YOUR_API_TOKEN"
FAQ
Do I need an API key? No. The openFDA API is completely free and requires no authentication. You only need an Apify account to run the actor.
How current is the recall data? The openFDA database is updated regularly by the FDA. Most recalls appear within days of being officially announced.
What is the difference between Class I, II, and III recalls? Class I is the most serious -- the device could cause serious injury or death. Class II means the device may cause temporary or reversible health problems. Class III means the device is unlikely to cause harm but still violates FDA regulations.
What is the classificationDate field? This is the date the FDA officially classified the recall severity (Class I, II, or III). It typically comes after the recall initiation date and provides insight into how quickly the FDA assessed severity. This field is unique to the device enforcement endpoint.
Can I get more than 5,000 results? The actor caps at 5,000 for performance reasons, and the openFDA API limits pagination to 25,000 records. For larger datasets, use date range filters to split queries into smaller time windows and combine the results across multiple runs.
What happens if no results match my filters?
The actor outputs a single record with error: true, failureType: "no-data", and a "No device recalls found" message, so you can tell "nothing matched" apart from "the API failed" (failureType is timeout, invalid-input, or api-error on genuine failures). The openFDA API returns a 404 when no results match, which the actor handles gracefully.
Use cases
- Medical device safety monitoring -- Track recalls for specific device categories (pacemakers, insulin pumps, imaging systems) with scheduled daily or weekly runs and webhook alerts to Slack or email.
- Supplier due diligence -- Investigate a device manufacturer's recall history before procurement decisions. Filter by company name to see all past enforcement actions.
- Regulatory compliance -- Monitor Class I and Class II recalls in your product category for compliance reporting and risk management.
- Healthcare facility risk management -- Track recalls for devices in your hospital or clinic inventory. Cross-reference recall numbers with your asset management system.
- Insurance and liability analysis -- Analyze recall patterns by classification, company, and time period to assess medical device liability risk.
- Journalism and public interest -- Investigate device safety trends, repeat offenders, or geographic patterns in FDA enforcement actions.
- Post-market surveillance research -- Combine with the FDA Device Adverse Events (MAUDE) actor to correlate adverse event reports with recall actions for specific device types.
Use in Dify
Drop this actor into Dify workflows via the Apify plugin's Run Actor node. Each recall returns triaged, classified, and recommended as structured JSON — act-immediately / assess-exposure / monitor / informational plus the severity and reasonCategory enums your downstream node branches on. A scraper pointed at the FDA recall pages returns raw HTML; this returns decisions.
- Actor ID:
ryanclinton/fda-device-recalls - Sample input (monitor a device category and act only on critical, unresolved recalls):
{"keyword": "infusion pump","classification": "Class I","status": "Ongoing","watchlistName": "infusion-pumps","maxResults": 200}
A Dify if/else node routes each record on the stable recommendedAction enum without parsing any prose:
IF recommendedAction == "act-immediately" → page the on-call quality lead (Slack/PagerDuty)ELIF recommendedAction == "assess-exposure" → open a review task with the recall numberELIF recommendedAction == "monitor" → append to the weekly digestELSE (informational) → archive
Layer a second branch on riskTier == "extreme", sort by attentionScore for "only the recalls that matter to me", route on reasonCategory (every software or sterility recall to a specialist), or branch on temporalSignals.changeFlag in ("ESCALATED", "RISK_INCREASED") when watchlistName is set — so a scheduled Dify run alerts only when a recall gets more dangerous. For a dashboard tile set outputMode: "dashboard" and read headlineRisk / classIActive / newThisRun; for a director-level summary set outputMode: "executive" and read riskTrajectory / recommendedActions / topThreats straight off the single object. The per-record summary string is usable verbatim in the notification body; no LLM rewriting required.
Related actors
FDA regulatory intelligence suite
| Actor | Description | Use together for |
|---|---|---|
| FDA 510(k) Device Clearances | Pre-market 510(k) clearance search | Pre-market clearance to post-market recall pipeline |
| FDA PMA Device Approvals | Class III PMA approval search | High-risk device approval to recall correlation |
| FDA Device Adverse Events (MAUDE) | Medical device adverse event reports | Adverse event signals leading to recall actions |
| FDA Drug Approval Search | NDA/ANDA/BLA drug approval search | Cross-domain FDA approval monitoring |
| openFDA Drug Event Monitor | FDA adverse drug event reports (FAERS) | Full FDA safety monitoring across drugs and devices |
| FDA Drug Recall Search | FDA drug enforcement actions | Complete recall coverage across drugs and devices |
| FDA Food Recall Monitor | FDA food enforcement actions | Complete FDA recall monitoring across all product types |
| FDA Food Adverse Events (CAERS) | Food/supplement adverse event reports | Full adverse event coverage across FDA domains |
| FDA Product Intelligence | Cross-domain FDA intelligence with risk assessment | Single query across all 9 openFDA endpoints |
| FDA Intelligence MCP | MCP server with 11 FDA tools | AI agent access to the full FDA intelligence suite |
Other safety and regulatory actors
| Actor | Description | Use together for |
|---|---|---|
| CPSC Product Recall Monitor | U.S. Consumer Product Safety Commission recalls | Multi-agency product safety tracking |
| Clinical Trial Tracker | ClinicalTrials.gov clinical study data | Device trials to post-market recall surveillance |
| NHTSA Vehicle Safety Search | Vehicle recall and complaint data | Comprehensive U.S. safety recall coverage |