openfda-api-reference
Reference file for the openFDA API skill. Do not trigger directly. Contains endpoint field details, composite workflows, pagination, response schemas, and troubleshooting. Loaded on demand by the main openfda-api skill.
openFDA API Reference
Table of Contents
- Drug Endpoint Fields
- Device Endpoint Fields
- Food/Tobacco/Other Endpoint Fields
- Composite Workflows
- Pagination
- Response Schemas
- Troubleshooting
1. Drug Endpoint Fields
drug/event (FAERS)
patient.drug.medicinalproduct- Drug name as reportedpatient.drug.openfda.brand_name/.generic_name- Standardized namespatient.reaction.reactionmeddrapt- Reaction (MedDRA PT)serious- 1=serious, 2=not seriousseriousnessdeath- 1=resulted in deathreceivedate- Date FDA received report (YYYYMMDD)occurcountry- Country codepatient.drug.drugcharacterization- 1=suspect, 2=concomitant, 3=interactingpatient.drug.drugindication- Reason drug was taken
drug/label (SPL)
openfda.brand_name/.generic_name/.manufacturer_nameopenfda.application_number- NDA/ANDAopenfda.product_type- "HUMAN PRESCRIPTION DRUG" or "HUMAN OTC DRUG"openfda.route/.substance_name/.rxcui/.spl_set_id- Sections:
boxed_warning,indications_and_usage,contraindications,warnings_and_precautions,adverse_reactions,drug_interactions,dosage_and_administration effective_time- Label date (YYYYMMDD)
drug/drugsfda (Approvals)
application_number- NDA/ANDA/BLAsponsor_name- Sponsor companyopenfda.brand_name/.generic_nameproducts[].brand_name/.dosage_form/.route/.active_ingredients/.te_codesubmissions[].submission_type(ORIG, SUPPL) /.submission_status(AP) /.submission_status_date- Note:
sponsor_name.exactdoesn't work for count; useopenfda.manufacturer_name.exact
drug/ndc (NDC Directory)
product_ndc/brand_name/generic_name/labeler_nameactive_ingredients(array with name/strength) /dosage_form/routemarketing_category(NDA, ANDA, BLA, OTC) /application_numberpackaging- NDC packaging variants
drug/enforcement (Recalls)
recall_number/reason_for_recall/classification(Class I/II/III)status/product_description/recalling_firmvoluntary_mandated/report_date/recall_initiation_datedistribution_pattern/openfda.brand_name
2. Device Endpoint Fields
device/event (MAUDE)
device[].generic_name/.brand_name/.manufacturer_d_name/.device_report_product_codemdr_text[].text- Narrative;.text_type_code- "Description of Event", "Manufacturer Narrative"event_type- Malfunction, Injury, Death, Otherdate_received(YYYY-MM-DD) /date_of_event/report_number/source_type
device/510k
k_number/device_name/applicant/decision_datedecision_description- SESE (substantially equivalent), etc.product_code/clearance_type(Traditional, Special, Abbreviated)advisory_committee/advisory_committee_description
device/pma
pma_number/supplement_number/applicant/generic_name/trade_namedecision_date/decision_code(APPR) /product_code/advisory_committee
device/classification
product_code(3-letter) /device_name/device_class(1/2/3)medical_specialty/medical_specialty_description/regulation_numberdefinition/implant_flag/life_sustain_support_flag/gmp_exempt_flag
device/udi (GUDID)
brand_name/catalog_number/company_name/device_descriptionidentifiers[].id/product_codes[].code/product_codes[].namesterilization.is_sterile/mri_safety/gmdn_terms
device/enforcement
Same fields as drug/enforcement.
3. Food/Tobacco/Other Endpoint Fields
food/event (CAERS)
products[].industry_name/.name_brand/.role("Suspect"/"Concomitant")reactions(array) /outcomes("Death", "Hospitalization", etc.)consumer.age/.gender/date_started/report_number
food/enforcement
Same fields as drug/enforcement.
tobacco/problem
date_submitted/tobacco_products/reported_health_problems/reported_product_problems
other/nsde
proprietary_name(case-sensitive) /application_number_or_citationproduct_type/package_ndc/package_ndc11/marketing_start_date/dosage_form
other/substance
names[].name- Search vianames.name:TERM(case-sensitive, uppercase)unii/codes[].code/.code_system(CAS, etc.)substance_class/structure/uuid/moieties
4. Composite Workflows
Safety Signal Scan
def safety_signal_scan(drug_name):
"""Top reactions, serious/non-serious counts, deaths, trend."""
results = {}
results["top_reactions"] = openfda_query("drug/event",
search=f"patient.drug.openfda.generic_name:{drug_name}",
count="patient.reaction.reactionmeddrapt.exact", limit=20)
for severity, label in [(1, "serious"), (2, "non_serious")]:
r = safe_query("drug/event",
search=f"patient.drug.openfda.generic_name:{drug_name}+AND+serious:{severity}", limit=1)
results[f"{label}_count"] = r.get("meta", {}).get("results", {}).get("total", 0)
r = safe_query("drug/event",
search=f"patient.drug.openfda.generic_name:{drug_name}+AND+seriousnessdeath:1", limit=1)
results["death_count"] = r.get("meta", {}).get("results", {}).get("total", 0)
results["trend"] = openfda_query("drug/event",
search=f"patient.drug.openfda.generic_name:{drug_name}", count="receivedate")
return results
Compare Drug Adverse Event Profiles
import time
def compare_drug_profiles(drug_a, drug_b, n_reactions=15):
"""Compare top adverse reactions between two drugs."""
profiles = {}
for drug in [drug_a, drug_b]:
r = openfda_query("drug/event",
search=f"patient.drug.openfda.generic_name:{drug}",
count="patient.reaction.reactionmeddrapt.exact", limit=n_reactions)
profiles[drug] = {item["term"]: item["count"] for item in r.get("results", [])}
time.sleep(0.5)
return profiles
Predicate Device Finder
def predicate_search(product_code, limit=20):
"""Find 510(k) cleared devices for predicate identification."""
clearances = openfda_query("device/510k",
search=f"product_code:{product_code}+AND+decision_description:SESE",
limit=limit, sort="decision_date:desc")
classification = safe_query("device/classification",
search=f"product_code:{product_code}", limit=1)
return {"classification": classification.get("results", []),
"clearances": clearances.get("results", [])}
Recall Intelligence
def recall_scan(product_name, categories=None):
"""Search recalls across drug, device, and food enforcement."""
if categories is None:
categories = ["drug", "device", "food"]
results = {}
for cat in categories:
try:
r = openfda_query(f"{cat}/enforcement",
search=f"product_description:{product_name}", limit=10)
results[cat] = r.get("results", [])
except Exception as e:
results[cat] = {"error": str(e)}
time.sleep(0.3)
return results
Per-Endpoint Query Examples
# FAERS: serious events in date range
def serious_events(drug_name, start="20240101", end="20241231", limit=10):
return openfda_query("drug/event",
search=f"patient.drug.openfda.generic_name:{drug_name}+AND+serious:1+AND+receivedate:[{start}+TO+{end}]",
limit=limit)
# Drug labeling by brand
def get_label(brand_name):
return openfda_query("drug/label", search=f'openfda.brand_name:"{brand_name}"', limit=1)
# Label by NDA/ANDA
def label_by_application(app_number):
return openfda_query("drug/label", search=f'openfda.application_number:"{app_number}"', limit=1)
# Drug approval by brand
def drug_approval(brand_name):
return openfda_query("drug/drugsfda", search=f'openfda.brand_name:"{brand_name}"', limit=5)
# NDC lookup
def lookup_ndc(ndc):
return openfda_query("drug/ndc", search=f'product_ndc:"{ndc}"', limit=1)
# Class I drug recalls
def class1_drug_recalls(start="20250101", limit=10):
return openfda_query("drug/enforcement",
search=f'classification:"Class I"+AND+report_date:[{start}+TO+20261231]', limit=limit)
# Device events by generic name
def device_events(device_name, limit=10):
return openfda_query("device/event", search=f'device.generic_name:"{device_name}"', limit=limit)
# 510(k) by applicant
def find_510k(applicant, limit=10):
return openfda_query("device/510k", search=f"applicant:{applicant}", limit=limit)
# PMA lookup
def find_pma(applicant=None, trade_name=None, limit=10):
search = f"applicant:{applicant}" if applicant else f"trade_name:{trade_name}" if trade_name else None
return openfda_query("device/pma", search=search, limit=limit)
# Device classification
def device_classification(product_code):
return openfda_query("device/classification", search=f"product_code:{product_code}", limit=5)
# UDI lookup
def udi_lookup(brand_name, limit=5):
return openfda_query("device/udi", search=f'brand_name:"{brand_name}"', limit=limit)
# Food events
def food_events(product_name, limit=10):
return openfda_query("food/event", search=f'products.name_brand:"{product_name}"', limit=limit)
5. Pagination
Skip-based, max skip+limit = 25,000.
def paginate_results(endpoint, search, max_results=5000, page_size=100):
all_results, skip = [], 0
while skip < max_results and skip < 25000:
r = openfda_query(endpoint, search=search, limit=page_size, skip=skip)
batch = r.get("results", [])
if not batch: break
all_results.extend(batch)
total = r.get("meta", {}).get("results", {}).get("total", 0)
skip += page_size
if skip >= total: break
time.sleep(0.3)
return all_results
For >25,000 records use bulk downloads: https://open.fda.gov/data/downloads/
6. Response Schemas
Standard response
{"meta": {"last_updated": "2026-01-27", "results": {"skip": 0, "limit": 10, "total": 419459}},
"results": [...]}
Count response
{"results": [{"term": "NAUSEA", "count": 752669}, {"term": "FATIGUE", "count": 742320}]}
Date count response
{"results": [{"time": "20240101", "count": 12345}]}
7. Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 404 | No matching records | Normal; use safe_query wrapper |
| 409 | Rate limit exceeded | Wait; add api_key |
| 400 "Invalid search syntax" | Malformed search | Check colons, brackets, quotes |
| Count returns single words | Missing .exact | Add .exact to text fields |
| Count returns SERVER_ERROR | Missing .exact on text field | Hard error; add .exact |
| Count returns 404 on numeric | Used .exact on numeric field | Remove .exact |
| Skip exceeds limit | skip+limit > 25,000 | Use bulk downloads |
| Wrong data in results | Wrong field path | Verify at open.fda.gov |