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

  1. Drug Endpoint Fields
  2. Device Endpoint Fields
  3. Food/Tobacco/Other Endpoint Fields
  4. Composite Workflows
  5. Pagination
  6. Response Schemas
  7. Troubleshooting

1. Drug Endpoint Fields

drug/event (FAERS)

  • patient.drug.medicinalproduct - Drug name as reported
  • patient.drug.openfda.brand_name / .generic_name - Standardized names
  • patient.reaction.reactionmeddrapt - Reaction (MedDRA PT)
  • serious - 1=serious, 2=not serious
  • seriousnessdeath - 1=resulted in death
  • receivedate - Date FDA received report (YYYYMMDD)
  • occurcountry - Country code
  • patient.drug.drugcharacterization - 1=suspect, 2=concomitant, 3=interacting
  • patient.drug.drugindication - Reason drug was taken

drug/label (SPL)

  • openfda.brand_name / .generic_name / .manufacturer_name
  • openfda.application_number - NDA/ANDA
  • openfda.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/BLA
  • sponsor_name - Sponsor company
  • openfda.brand_name / .generic_name
  • products[].brand_name / .dosage_form / .route / .active_ingredients / .te_code
  • submissions[].submission_type (ORIG, SUPPL) / .submission_status (AP) / .submission_status_date
  • Note: sponsor_name.exact doesn't work for count; use openfda.manufacturer_name.exact

drug/ndc (NDC Directory)

  • product_ndc / brand_name / generic_name / labeler_name
  • active_ingredients (array with name/strength) / dosage_form / route
  • marketing_category (NDA, ANDA, BLA, OTC) / application_number
  • packaging - NDC packaging variants

drug/enforcement (Recalls)

  • recall_number / reason_for_recall / classification (Class I/II/III)
  • status / product_description / recalling_firm
  • voluntary_mandated / report_date / recall_initiation_date
  • distribution_pattern / openfda.brand_name

2. Device Endpoint Fields

device/event (MAUDE)

  • device[].generic_name / .brand_name / .manufacturer_d_name / .device_report_product_code
  • mdr_text[].text - Narrative; .text_type_code - "Description of Event", "Manufacturer Narrative"
  • event_type - Malfunction, Injury, Death, Other
  • date_received (YYYY-MM-DD) / date_of_event / report_number / source_type

device/510k

  • k_number / device_name / applicant / decision_date
  • decision_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_name
  • decision_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_number
  • definition / implant_flag / life_sustain_support_flag / gmp_exempt_flag

device/udi (GUDID)

  • brand_name / catalog_number / company_name / device_description
  • identifiers[].id / product_codes[].code / product_codes[].name
  • sterilization.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_citation
  • product_type / package_ndc / package_ndc11 / marketing_start_date / dosage_form

other/substance

  • names[].name - Search via names.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

ErrorCauseFix
404No matching recordsNormal; use safe_query wrapper
409Rate limit exceededWait; add api_key
400 "Invalid search syntax"Malformed searchCheck colons, brackets, quotes
Count returns single wordsMissing .exactAdd .exact to text fields
Count returns SERVER_ERRORMissing .exact on text fieldHard error; add .exact
Count returns 404 on numericUsed .exact on numeric fieldRemove .exact
Skip exceeds limitskip+limit > 25,000Use bulk downloads
Wrong data in resultsWrong field pathVerify at open.fda.gov