Medical-research-skills fda-database
Query the openFDA API to retrieve FDA regulatory datasets (drugs, devices, adverse events, recalls, submissions, UNII) when you need programmatic safety/regulatory evidence for analysis or research.
install
source · Clone the upstream repo
git clone https://github.com/aipoch/medical-research-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/aipoch/medical-research-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/scientific-skills/Evidence Insight/fda-database" ~/.claude/skills/aipoch-medical-research-skills-fda-database && rm -rf "$T"
manifest:
scientific-skills/Evidence Insight/fda-database/SKILL.mdsource content
When to Use
- Pharmacovigilance / safety signal screening when you need adverse event counts, common reactions, or serious-event rates for a drug.
- Medical device regulatory research when you need 510(k)/PMA context, device classification, UDI lookups, or device adverse events/recalls.
- Recall and enforcement monitoring when you need to track Class I/II/III recalls across drugs, devices, or foods.
- Substance identity resolution when you need UNII/CAS/name-based lookups and basic substance relationship/structure retrieval.
- Veterinary safety analysis when you need animal adverse events filtered by species/breed and product.
Key Features
- Unified Python interface (
) for multiple openFDA domains (drug, device, food, animalandveterinary, other).FDAQuery - Convenience helpers for common tasks:
- Drug events, labels, recalls, shortages
- Device events, classification, 510(k), PMA, UDI
- Food events and recalls
- Animal/veterinary adverse events
- Substance (UNII/name) lookups
- Supports openFDA query patterns:
- Fielded search strings, date ranges, wildcards
- Aggregations via
(withcount_by_field(...)
support).exact - Pagination via
and bulk retrieval viaskip/limitquery_all(...)
- Operational safeguards:
- Optional API key support for higher daily limits
- Built-in caching (TTL) and rate limiting (as implemented in
)scripts/fda_query.py - Basic error handling patterns
Additional endpoint notes and query syntax are typically documented in:
,references/api_basics.md,references/drugs.md,references/devices.md,references/foods.md,references/animal_veterinary.md.references/other.md
Dependencies
- Python 3.9+
- openFDA API access (public)
- Optional: openFDA API key (recommended for higher daily quota)
Package-level dependencies (e.g.,
) are defined by the repository implementation inrequests. If you maintain this skill, pin them inscripts/fda_query.py(for example,requirements.txt) to ensure reproducibility.requests==2.31.0
Example Usage
The following example is designed to be runnable in a repository that contains
scripts/fda_query.py and the FDAQuery class.
1) Set an API key (optional, recommended)
export FDA_API_KEY="your_key_here"
2) Run a complete script
import os from datetime import datetime, timedelta from scripts.fda_query import FDAQuery def drug_safety_profile(fda: FDAQuery, drug_name: str): # Total adverse events (meta.total) events = fda.query_drug_events(drug_name, limit=1) total = events.get("meta", {}).get("results", {}).get("total", 0) # Top reactions (aggregation) reactions = fda.count_by_field( "drug", "event", search=f"patient.drug.medicinalproduct:*{drug_name}*", field="patient.reaction.reactionmeddrapt", exact=True, ) top_reactions = reactions.get("results", [])[:10] # Serious events serious = fda.query( "drug", "event", search=f"patient.drug.medicinalproduct:*{drug_name}*+AND+serious:1", limit=1, ) serious_total = serious.get("meta", {}).get("results", {}).get("total", 0) # Recent recalls recalls = fda.query_drug_recalls(drug_name=drug_name) recall_results = recalls.get("results", []) return { "drug": drug_name, "total_events": total, "serious_events": serious_total, "serious_rate_pct": (serious_total / total * 100.0) if total else 0.0, "top_reactions": top_reactions, "recalls_sample": recall_results[:5], } def monthly_event_trend(fda: FDAQuery, drug_name: str, months: int = 6): trends = [] for i in range(months): end = datetime.now() - timedelta(days=30 * i) start = end - timedelta(days=30) date_range = f"[{start.strftime('%Y%m%d')}+TO+{end.strftime('%Y%m%d')}]" search = ( f"patient.drug.medicinalproduct:*{drug_name}*" f"+AND+receivedate:{date_range}" ) result = fda.query("drug", "event", search=search, limit=1) count = result.get("meta", {}).get("results", {}).get("total", 0) trends.append({"month": start.strftime("%Y-%m"), "events": count}) return list(reversed(trends)) def main(): fda = FDAQuery(api_key=os.getenv("FDA_API_KEY")) # Drug: safety profile + trend profile = drug_safety_profile(fda, "aspirin") trend = monthly_event_trend(fda, "aspirin", months=6) # Device: quick cross-database lookup device_lookup = { "adverse_events": fda.query_device_events("pacemaker", limit=10), "classification": fda.query_device_classification("DQY"), "510k": fda.query_device_510k(applicant="Medtronic"), "udi": fda.query("device", "udi", search="brand_name:*pacemaker*", limit=5), } # Food: recall monitoring food_recalls = fda.query_food_recalls(reason="undeclared peanut", limit=10) # Substance: UNII lookup substance = fda.query_substance_by_unii("R16CO5Y76E") print({"drug_profile": profile, "drug_trend": trend}) print({"device_lookup_keys": list(device_lookup.keys())}) print({"food_recalls_count": len(food_recalls.get("results", []))}) print({"substance_keys": list(substance.keys())}) if __name__ == "__main__": main()
3) Run the repository examples (if provided)
python scripts/fda_examples.py
Implementation Details
API domains and endpoints
This skill is a thin client over openFDA endpoints, typically accessed as:
- Drugs:
,drug/event
,drug/label
,drug/ndc
,drug/enforcement
,drug/drugsfdadrug/drugshortages - Devices:
,device/event
,device/510k
,device/classification
,device/enforcement
,device/recall
,device/pma
,device/registrationlisting
,device/udidevice/covid19serology - Foods:
,food/eventfood/enforcement - Animal/Veterinary:
animalandveterinary/event - Other/Substances:
,other/substanceother/nsde
Exact helper method names (e.g.,
query_drug_events, query_device_510k) are implemented in scripts/fda_query.py.
Query construction
- Searches are passed as openFDA query strings (Lucene-like), e.g.:
- Field match:
patient.drug.medicinalproduct:aspirin - Wildcards:
(use sparingly)*aspirin* - Boolean:
A+AND+B - Date range:
receivedate:[20240101+TO+20241231]
- Field match:
- Pagination uses:
(page size)limit
(offset)skip
- Aggregations use
:count_by_field(domain, endpoint, search, field, exact=True)- When
, the implementation typically appendsexact=True
to the aggregation field to avoid tokenization issues..exact
- When
Rate limits and authentication
- openFDA supports unauthenticated access with lower daily quotas; an API key increases the daily request limit.
- The client is expected to:
- Attach the API key when provided
- Apply rate limiting and retries (per
implementation)FDAQuery
Result handling and robustness
- Responses generally follow:
{ "meta": { "results": { "skip": 0, "limit": 100, "total": 12345 } }, "results": [] }
- Always guard for:
- Missing
results - Empty result sets
objects returned by the APIerror
- Missing
Caching
- If enabled in
, caching reduces repeated calls for identical queries.FDAQuery - Typical parameters (implementation-dependent):
use_cache=Truecache_ttl=<seconds>