Building a Pharma Compliance Alert System with the FDA Drug & Safety API
Regulatory compliance in pharmaceuticals isn't optional — it's existential. A missed FDA enforcement action, an unmonitored recall, or a delayed adverse-event flag can cost a company millions in fines, product liability, and reputational damage. Yet most compliance teams still rely on manually checking FDA.gov, email newsletters, or expensive legacy platforms that cost $50K+/year.
Here's the thing: the FDA publishes all of this data for free via openFDA. And there's now a clean REST API that wraps it into developer-friendly endpoints so you can build your own compliance alert pipeline in an afternoon.
In this guide I'll show you how to build a lightweight pharma compliance monitoring system using the FDA Drug & Safety API — covering enforcement actions, device recalls, and adverse event spikes — with real curl examples and a Python automation script you can run on a cron schedule.
Why Build Your Own Compliance Monitor?
Commercial pharmacovigilance platforms (Veeva Vault, Aris Global, Oracle Argus) are powerful, but they're built for enterprise teams with enterprise budgets. If you're a:
- Health-tech startup building a drug safety feature into your product
- Compliance consultant who wants to send automated client alerts
- Investor tracking FDA risk exposure across a portfolio
- Hospital IT team monitoring device recalls for your procurement list
...then you don't need a six-figure contract. You need a good API and a Python script.
The API: Endpoints We'll Use
Base URL: https://fda-drug-safety-api.onrender.com
All requests require the header: x-api-key: YOUR_API_KEY
There are six core endpoints:
| Endpoint | What It Returns |
|---|---|
/drug/search |
Drug lookup by name (brand/generic) |
/drug/adverse-events |
FAERS adverse event reports |
/drug/label |
Full prescribing info / warnings |
/device/recalls |
FDA device recall database |
/enforcement |
Drug enforcement actions and recalls |
/health |
API status check |
Step 1: Explore Enforcement Actions
Enforcement actions are the bread and butter of any compliance alert system. These cover recalls, market withdrawals, and import alerts.
curl -s "https://fda-drug-safety-api.onrender.com/enforcement?limit=3" \
-H "x-api-key: YOUR_API_KEY"
Sample response:
{
"total_found": 17681,
"results": [
{
"recall_number": "D-0115-2026",
"recall_initiation_date": "20251015",
"classification": "Class II",
"product_description": "Semaglutide Injection, 10 mg/4 mL...",
"reason": "Lack of Assurance of Sterility",
"recalling_firm": "ProRx LLC",
"state": "PA",
"status": "Ongoing",
"voluntary_mandated": "Voluntary: Firm initiated",
"distribution_pattern": "TX and UT"
}
]
}
Notice the classification field — Class I is the most serious (risk of serious injury or death), Class II is a possible temporary health consequence, Class III is unlikely to cause harm. Your alert system should treat Class I events as immediate priority.
Step 2: Monitor Device Recalls
Medical device recalls affect hospitals, surgical centers, and any company with devices in their supply chain. Pull the latest:
curl -s "https://fda-drug-safety-api.onrender.com/device/recalls?limit=5" \
-H "x-api-key: YOUR_API_KEY"
Filter by keyword to track specific device categories relevant to your organization:
curl -s "https://fda-drug-safety-api.onrender.com/device/recalls?keyword=insulin+pump&limit=5" \
-H "x-api-key: YOUR_API_KEY"
This is especially useful for hospital procurement teams who need to know if a device currently in service has an active recall.
Step 3: Track Adverse Event Spikes
Adverse event monitoring is critical for pharmacovigilance. The /drug/adverse-events endpoint queries the FDA Adverse Event Reporting System (FAERS), which contains over 15 million reports going back decades.
curl -s "https://fda-drug-safety-api.onrender.com/drug/adverse-events?name=aspirin&limit=5" \
-H "x-api-key: YOUR_API_KEY"
Sample response:
{
"drug": "aspirin",
"total_reports": 609473,
"results": [
{
"report_id": "10003304",
"receive_date": "20140312",
"serious": false,
"serious_criteria": {
"death": false,
"hospitalization": false,
"life_threatening": false,
"disability": false
},
"patient_sex": "female",
"reactions": ["Drug hypersensitivity"],
"drugs_taken": ["ASPIRIN", "OXYCONTIN", "TRAMADOL HYDROCHLORIDE"]
}
]
}
For a compliance system, you'd track the serious: true count over rolling time windows. A sudden spike in serious adverse events for a drug in your portfolio is an early regulatory warning signal.
Step 4: The Python Compliance Alert Script
Here's a production-ready Python script that runs on a daily cron schedule, pulls new enforcement actions and device recalls, filters for high-severity events, and outputs a structured alert digest.
import requests
import json
from datetime import datetime
API_BASE = "https://fda-drug-safety-api.onrender.com"
API_KEY = "YOUR_API_KEY"
HEADERS = {"x-api-key": API_KEY}
# --- Configuration ---
WATCH_DRUGS = ["semaglutide", "metformin", "ozempic", "wegovy"]
WATCH_DEVICES = ["insulin pump", "pacemaker", "ventilator"]
ALERT_CLASSIFICATIONS = ["Class I"] # Highest severity only
def get_enforcement_actions(limit=50):
url = f"{API_BASE}/enforcement"
resp = requests.get(url, headers=HEADERS, params={"limit": limit})
resp.raise_for_status()
return resp.json().get("results", [])
def get_device_recalls(keyword=None, limit=20):
url = f"{API_BASE}/device/recalls"
params = {"limit": limit}
if keyword:
params["keyword"] = keyword
resp = requests.get(url, headers=HEADERS, params=params)
resp.raise_for_status()
return resp.json().get("results", [])
def get_adverse_event_count(drug_name):
url = f"{API_BASE}/drug/adverse-events"
resp = requests.get(url, headers=HEADERS, params={"name": drug_name, "limit": 1})
resp.raise_for_status()
return resp.json().get("total_reports", 0)
def filter_high_severity(enforcement_actions):
return [
action for action in enforcement_actions
if action.get("classification") in ALERT_CLASSIFICATIONS
and action.get("status") == "Ongoing"
]
def build_compliance_report():
report = {
"generated_at": datetime.utcnow().isoformat(),
"high_severity_enforcement": [],
"device_recall_alerts": [],
"adverse_event_counts": {}
}
# 1. Enforcement actions — filter for Class I
all_actions = get_enforcement_actions(limit=100)
report["high_severity_enforcement"] = filter_high_severity(all_actions)
# 2. Device recalls for watched device categories
for keyword in WATCH_DEVICES:
recalls = get_device_recalls(keyword=keyword, limit=5)
report["device_recall_alerts"].extend(
[{**r, "_matched_keyword": keyword} for r in recalls]
)
# 3. Adverse event totals for watched drugs
for drug in WATCH_DRUGS:
report["adverse_event_counts"][drug] = get_adverse_event_count(drug)
return report
def format_digest(report):
lines = [
f"FDA Compliance Digest — {report['generated_at'][:10]}",
"=" * 50,
f"HIGH-SEVERITY ENFORCEMENT ({len(report['high_severity_enforcement'])} Class I, Ongoing)",
]
for action in report["high_severity_enforcement"][:5]:
lines.append(f" [{action.get('classification')}] {action.get('recalling_firm')}")
lines.append(f" Product: {str(action.get('product_description', ''))[:80]}...")
lines.append(f" Reason: {str(action.get('reason', ''))[:80]}...")
lines.append("")
lines.append(f"DEVICE RECALLS ({len(report['device_recall_alerts'])} matched)")
for recall in report["device_recall_alerts"][:5]:
lines.append(f" [{recall.get('_matched_keyword')}] {str(recall.get('product_description', ''))[:80]}...")
lines.append("")
lines.append("ADVERSE EVENT TOTALS")
for drug, count in report["adverse_event_counts"].items():
lines.append(f" {drug.title()}: {count:,} reports")
return "\n".join(lines)
if __name__ == "__main__":
report = build_compliance_report()
# Save JSON snapshot
filename = f"compliance_{datetime.utcnow().strftime('%Y%m%d')}.json"
with open(filename, "w") as f:
json.dump(report, f, indent=2)
digest = format_digest(report)
print(digest)
# Plug in your delivery layer:
# requests.post(SLACK_WEBHOOK, json={"text": digest}) # Slack
# sendgrid.send(to="team@yourco.com", body=digest) # Email
# requests.post(PAGERDUTY_URL, json={"payload": digest}) # PagerDuty (Class I)
Step 5: Automate with Cron or a Serverless Scheduler
# Run every morning at 7am UTC
0 7 * * * cd /opt/compliance && python3 fda_compliance_monitor.py >> logs/fda.log 2>&1
Or deploy serverlessly:
- AWS Lambda + EventBridge (free tier easily covers daily runs)
- Railway.app cron job (one-click deploy from GitHub)
- GitHub Actions scheduled workflow (completely free)
The API is stateless and fast — a complete compliance sweep takes under 5 seconds.
What to Build on Top of This
Once the data pipeline is running, real value comes from enrichment and routing:
-
Slack alerts — Route Class I recalls to
#compliance-alertsthe moment they appear - Competitor monitoring — Watch enforcement actions by specific firm names
- Historical trending — Store adverse event counts in Postgres, alert on weekly spikes > 20%
- Regulatory dashboard — Feed Metabase or Grafana for a visual compliance calendar
- Portfolio risk scoring — Aggregate enforcement exposure across all drugs a pharma company manufactures (useful for investors and M&A due diligence)
Get API Access
The FDA Drug & Safety API is available on RapidAPI — search "FDA Drug Safety API" to find the listing, review usage tiers, and get your API key.
Direct API base: https://fda-drug-safety-api.onrender.com
All data is sourced from openFDA (public domain). The API provides a clean, normalized abstraction layer so you spend time building — not wrestling with raw openFDA pagination, field normalization, and response inconsistencies.
Stay in the Loop
Building at the intersection of AI, automation, and health data? I publish weekly breakdowns of tools, APIs, and business opportunities worth knowing about.
Get weekly AI business & automation insights → AI Business Trends on Substack
Built something cool with this API? Drop it in the comments — especially if you've wired it to Slack or a compliance dashboard.
Top comments (0)