openFDA Search and Query
Prerequisites
uv: Read the uv skill and follow its Setup instructions to ensure
uv is installed and on PATH.
- User Notification: If .licenses/openfda_database_LICENSE.txt does not
already exist in the workspace root directory then (1) prominently notify
the user to check the terms at https://open.fda.gov/apis/ and
https://open.fda.gov/license, then (2) create the file recording the
notification text and timestamp.
.env file: Make sure the .env file exists in your home directory.
Create one if it does not exist.
FDA_API_KEY (optional but recommended): Raises the daily request limit
from 1,000 to 120,000. The skill works without it, but an agent can easily
exhaust the keyless limit in a single session. You can register for a free
key at https://open.fda.gov/apis/authentication/. You MUST use the safe
credentials protocol in the credentials skill to check for and request
this key if this skill looks relevant to the user's request.
Core Rules
Use the Wrapper: ALWAYS execute the provided helper scripts to query the
database rather than accessing the database directly. The scripts
automatically enforce the required rate limit gracefully.
Rate Limiting: Respect openFDA rate limits. Without API key: 240
requests/min, 1,000 requests/day per IP. With API key: 240 requests/min,
120,000 requests/day per key. Always set an API key before running
multi-query workflows.
Warning: An automated agent can easily exhaust the 1,000-request daily
limit in a single research session. Always set an API key before running
multi-query workflows.
You MUST use the safe credentials protocol in the credentials skill to
help the user add FDA_API_KEY to their .env file if this skill looks
relevant to the user's request. The script will emit a warning to stderr if no
API key is detected.
Always Use --output: All subcommands require --output <file> to
write results to a file. This prevents large output becoming overwhelming.
Use jq or code to read the output file.
Notification: If this skill is used, ensure this is mentioned in the
output.
Utility Script
Single script for all operations:
uv run scripts/openfda_query.py {search,count,download} --output <file> [options]
1. Search
Search any of the 28 endpoints and save JSON results to a file.
uv run scripts/openfda_query.py search \
--category drug --endpoint event \
--search "patient.drug.medicinalproduct:aspirin" \
--limit 5 --output /tmp/fda_results.json
Stdout prints a compact summary:
{"status": "success", "output": "/tmp/fda_results.json", "results_in_file": 5, "total_matching": 601477}
Options:
--output: Output file for full JSON results (required).
--category: API category — drug, device, food, tobacco, other,
animalandveterinary, cosmetic, transparency.
--endpoint: Endpoint within the category (e.g., event, label, 510k).
See references/api_endpoints.md for full
list.
--search: Query string (e.g.,
patient.drug.medicinalproduct:aspirin+AND+serious:1).
--sort: Sort field and order (e.g., receivedate:desc).
--limit: Max results (default 10, max 1000).
--skip: Pagination offset (default 0).
--api_key: API key (also reads FDA_API_KEY env var).
2. Count
Count unique values of a field within matching results.
uv run scripts/openfda_query.py count \
--category drug --endpoint event \
--search "patient.drug.medicinalproduct:aspirin" \
--count_field "patient.reaction.reactionmeddrapt.exact" \
--summary 10 --output /tmp/aspirin_reactions.json
Stdout prints a summary with the top 5 terms. Full data is in the output file.
Additional options:
--count_field: Field to count (append .exact for whole-phrase counting).
--summary N: Return only the top N most frequent terms. Use this to avoid
flooding the context with hundreds of infrequent terms.
3. Download
Download multiple pages of results to a file.
uv run scripts/openfda_query.py download \
--category drug --endpoint event \
--search "patient.drug.medicinalproduct:aspirin" \
--limit 100 --max_pages 5 \
--output /tmp/aspirin_events.json
Additional options:
--max_pages: Maximum pages to fetch (default 10).
--all_results: Automatically paginate to fetch all matching results.
Safety cap of 25,000 records maximum per download to prevent runaway
downloads and prevent excessive API usage.
Tip: Common drugs can have excessive reports. Use a date range (e.g.,
receivedate:[20250101+TO+20250131]) to limit the volume of download.
Entity Resolution: Using .exact for Precision
When searching for specific product names, drug names, or categorical terms,
always use the .exact suffix on the field to get exact-match results. Without
it, the API tokenizes multi-word values and returns noisy partial matches.
# Precise: matches only "ADVIL"
uv run scripts/openfda_query.py search --category drug --endpoint label \
--search 'openfda.brand_name.exact:"ADVIL"' \
--limit 5 --output /tmp/advil_label.json
Note: Many brand names in the FDA database include variant suffixes (e.g.,
"TYLENOL Extra Strength" rather than just "TYLENOL"). If an .exact search
returns 0 results, try without .exact to see the available brand name
variants, then re-query with the full exact name.
The .exact suffix is also required when using --count_field to aggregate
whole phrases instead of individual words.
MedDRA Term Resolution
openFDA adverse event data uses MedDRA (Medical Dictionary for Regulatory
Activities) terms for reactions. The API reports Preferred Terms (PTs) but
does not provide the MedDRA hierarchy (System Organ Class, High Level Terms,
etc.).
Note: MedDRA is a proprietary ontology and is not indexed in the
EMBL-EBI OLS. To approximate MedDRA hierarchy lookups, use the Human
Phenotype Ontology (HP) or NCI Thesaurus (NCIT) as proxy ontologies —
they cross-reference MedDRA IDs and provide parent/ancestor relationships.
# Step 1: Get top reactions from openFDA
uv run scripts/openfda_query.py count \
--category drug --endpoint event \
--search "patient.drug.medicinalproduct:metformin" \
--count_field "patient.reaction.reactionmeddrapt.exact" \
--summary 5 --output /tmp/metformin_reactions.json
# Step 2: Look up the top reaction term using a biomedical ontology service
# skill (e.g. embl-ebi-ols skill).
# MedDRA is not available in OLS; use the Human Phenotype Ontology (HP) or
# NCI Thesaurus (NCIT) as a proxy to find the hierarchical classification of
# the reaction term.
Available Endpoints (28 total)
Category to endpoint mapping:
drug: event, label, ndc, enforcement, drugsfda, shortages
device: 510k, classification, enforcement, event, pma, recall,
registrationlisting, udi, covid19serology
food: enforcement, event
tobacco: problem, researchpreventionads, researchdigitalads,
researchsmokefree
other: historicaldocument, nsde, substance, unii
animalandveterinary: event
cosmetic: event
transparency: crl
Reference
- Query syntax and all endpoints: See
references/api_endpoints.md for field names,
search syntax, date ranges, and boolean operators.
Recipes
Common query patterns for drugs, devices, foods, tobacco, cosmetics, animal and
veterinary products, substances, transparency data, adverse events, recalls,
labeling, approvals, shortages, 510(k) clearances, NDC lookups, any FDA safety
or regulatory data query, and more. See
references/recipes.md for the full recipes.
Workflow
- Search for records using
search with --output. Read the output file.
- Use
count with --summary 10 --output to summarize field distributions.
- Use
download (with --all_results for exhaustive pulls) to fetch larger
datasets.
- Read and analyze the output file using standard tools.
- For MedDRA term hierarchy questions, use a biomedical ontology service skill
(e.g. EMBL-EBI OLS skill with the HP or NCIT ontology) to look up the term.
1---2name: openfda-database3description: >4 Query, search, and download data from the openFDA API for drugs, devices,5 foods, tobacco, cosmetics, animal and veterinary products, substances, and6 transparency data. Use for FDA adverse events, recalls, labeling, approvals,7 shortages, 510(k) clearances, NDC lookups, and any FDA safety or regulatory8 data query across all 28 API endpoints.9---1011# openFDA Search and Query1213## Prerequisites14151. **`uv`**: Read the `uv` skill and follow its Setup instructions to ensure16 `uv` is installed and on PATH.172. **User Notification**: If .licenses/openfda_database_LICENSE.txt does not18 already exist in the workspace root directory then (1) prominently notify19 the user to check the terms at https://open.fda.gov/apis/ and20 https://open.fda.gov/license, then (2) create the file recording the21 notification text and timestamp.223. **`.env` file**: Make sure the `.env` file exists in your home directory.23 Create one if it does not exist.244. **`FDA_API_KEY`** (optional but recommended): Raises the daily request limit25 from 1,000 to 120,000. The skill works without it, but an agent can easily26 exhaust the keyless limit in a single session. You can register for a free27 key at https://open.fda.gov/apis/authentication/. You **MUST** use the safe28 credentials protocol in the `credentials` skill to check for and request29 this key if this skill looks relevant to the user's request.3031## Core Rules3233- **Use the Wrapper**: ALWAYS execute the provided helper scripts to query the34 database rather than accessing the database directly. The scripts35 automatically enforce the required rate limit gracefully.3637- **Rate Limiting**: Respect openFDA rate limits. Without API key: 24038 requests/min, 1,000 requests/day per IP. With API key: 240 requests/min,39 120,000 requests/day per key. Always set an API key before running40 multi-query workflows.4142> **Warning**: An automated agent can easily exhaust the 1,000-request daily43> limit in a single research session. Always set an API key before running44> multi-query workflows.4546> You **MUST** use the safe credentials protocol in the `credentials` skill to47> help the user add `FDA_API_KEY` to their `.env` file if this skill looks48> relevant to the user's request. The script will emit a warning to stderr if no49> API key is detected.5051- **Always Use `--output`**: All subcommands require `--output <file>` to52 write results to a file. This prevents large output becoming overwhelming.53 Use jq or code to read the output file.5455- **Notification**: If this skill is used, ensure this is mentioned in the56 output.5758## Utility Script5960**Single script for all operations:**6162```bash63uv run scripts/openfda_query.py {search,count,download} --output <file> [options]64```6566### 1. Search6768Search any of the 28 endpoints and save JSON results to a file.6970```bash71uv run scripts/openfda_query.py search \72 --category drug --endpoint event \73 --search "patient.drug.medicinalproduct:aspirin" \74 --limit 5 --output /tmp/fda_results.json75```7677Stdout prints a compact summary:7879```json80{"status": "success", "output": "/tmp/fda_results.json", "results_in_file": 5, "total_matching": 601477}81```8283*Options:*8485- `--output`: Output file for full JSON results (required).86- `--category`: API category — `drug`, `device`, `food`, `tobacco`, `other`,87 `animalandveterinary`, `cosmetic`, `transparency`.88- `--endpoint`: Endpoint within the category (e.g., `event`, `label`, `510k`).89 See [references/api_endpoints.md](references/api_endpoints.md) for full90 list.91- `--search`: Query string (e.g.,92 `patient.drug.medicinalproduct:aspirin+AND+serious:1`).93- `--sort`: Sort field and order (e.g., `receivedate:desc`).94- `--limit`: Max results (default 10, max 1000).95- `--skip`: Pagination offset (default 0).96- `--api_key`: API key (also reads `FDA_API_KEY` env var).9798### 2. Count99100Count unique values of a field within matching results.101102```bash103uv run scripts/openfda_query.py count \104 --category drug --endpoint event \105 --search "patient.drug.medicinalproduct:aspirin" \106 --count_field "patient.reaction.reactionmeddrapt.exact" \107 --summary 10 --output /tmp/aspirin_reactions.json108```109110Stdout prints a summary with the top 5 terms. Full data is in the output file.111112*Additional options:*113114- `--count_field`: Field to count (append `.exact` for whole-phrase counting).115- `--summary N`: Return only the top N most frequent terms. Use this to avoid116 flooding the context with hundreds of infrequent terms.117118### 3. Download119120Download multiple pages of results to a file.121122```bash123uv run scripts/openfda_query.py download \124 --category drug --endpoint event \125 --search "patient.drug.medicinalproduct:aspirin" \126 --limit 100 --max_pages 5 \127 --output /tmp/aspirin_events.json128```129130*Additional options:*131132- `--max_pages`: Maximum pages to fetch (default 10).133- `--all_results`: Automatically paginate to fetch all matching results.134 Safety cap of 25,000 records maximum per download to prevent runaway135 downloads and prevent excessive API usage.136137 > **Tip**: Common drugs can have excessive reports. Use a date range (e.g.,138 > `receivedate:[20250101+TO+20250131]`) to limit the volume of download.139140## Entity Resolution: Using .exact for Precision141142When searching for specific product names, drug names, or categorical terms,143always use the `.exact` suffix on the field to get exact-match results. Without144it, the API tokenizes multi-word values and returns noisy partial matches.145146```bash147# Precise: matches only "ADVIL"148uv run scripts/openfda_query.py search --category drug --endpoint label \149 --search 'openfda.brand_name.exact:"ADVIL"' \150 --limit 5 --output /tmp/advil_label.json151```152153> **Note**: Many brand names in the FDA database include variant suffixes (e.g.,154> "TYLENOL Extra Strength" rather than just "TYLENOL"). If an `.exact` search155> returns 0 results, try without `.exact` to see the available brand name156> variants, then re-query with the full exact name.157158The `.exact` suffix is also required when using `--count_field` to aggregate159whole phrases instead of individual words.160161## MedDRA Term Resolution162163openFDA adverse event data uses MedDRA (Medical Dictionary for Regulatory164Activities) terms for reactions. The API reports **Preferred Terms (PTs)** but165does not provide the MedDRA hierarchy (System Organ Class, High Level Terms,166etc.).167168> **Note**: MedDRA is a proprietary ontology and is **not indexed** in the169> EMBL-EBI OLS. To approximate MedDRA hierarchy lookups, use the **Human170> Phenotype Ontology (HP)** or **NCI Thesaurus (NCIT)** as proxy ontologies —171> they cross-reference MedDRA IDs and provide parent/ancestor relationships.172173```bash174# Step 1: Get top reactions from openFDA175uv run scripts/openfda_query.py count \176 --category drug --endpoint event \177 --search "patient.drug.medicinalproduct:metformin" \178 --count_field "patient.reaction.reactionmeddrapt.exact" \179 --summary 5 --output /tmp/metformin_reactions.json180181# Step 2: Look up the top reaction term using a biomedical ontology service182# skill (e.g. embl-ebi-ols skill).183# MedDRA is not available in OLS; use the Human Phenotype Ontology (HP) or184# NCI Thesaurus (NCIT) as a proxy to find the hierarchical classification of185# the reaction term.186```187188## Available Endpoints (28 total)189190Category to endpoint mapping:191192- `drug`: event, label, ndc, enforcement, drugsfda, shortages193- `device`: 510k, classification, enforcement, event, pma, recall,194 registrationlisting, udi, covid19serology195- `food`: enforcement, event196- `tobacco`: problem, researchpreventionads, researchdigitalads,197 researchsmokefree198- `other`: historicaldocument, nsde, substance, unii199- `animalandveterinary`: event200- `cosmetic`: event201- `transparency`: crl202203## Reference204205- **Query syntax and all endpoints**: See206 [references/api_endpoints.md](references/api_endpoints.md) for field names,207 search syntax, date ranges, and boolean operators.208209## Recipes210211Common query patterns for drugs, devices, foods, tobacco, cosmetics, animal and212veterinary products, substances, transparency data, adverse events, recalls,213labeling, approvals, shortages, 510(k) clearances, NDC lookups, any FDA safety214or regulatory data query, and more. See215[references/recipes.md](references/recipes.md) for the full recipes.216217## Workflow2182191. Search for records using `search` with `--output`. Read the output file.2202. Use `count` with `--summary 10 --output` to summarize field distributions.2213. Use `download` (with `--all_results` for exhaustive pulls) to fetch larger222 datasets.2234. Read and analyze the output file using standard tools.2245. For MedDRA term hierarchy questions, use a biomedical ontology service skill225 (e.g. EMBL-EBI OLS skill with the HP or NCIT ontology) to look up the term.