| name | openfda |
| description | Query the FDA's public openFDA APIs for post-market drug data — FAERS adverse-event reports, Drugs@FDA approval and submission history, Structured Product Labels including boxed warnings, the National Drug Code directory, recall enforcement reports, and drug shortages. Use this skill to check what a regulator has already concluded about a molecule or its class, to date an approval and count its efficacy supplements, to read an approved indication or boxed warning, and to score a drug-event pair for disproportionate reporting with PRR, ROR, and chi-squared. Also trigger on openFDA, api.fda.gov, FAERS, Drugs@FDA, SPL, NDC, pharmacovigilance, boxed warning, adverse event report, drug recall, or safety signal. |
| license | MIT |
| allowed-tools | Read Write Edit Bash |
| compatibility | Requires Python 3.10+ and outbound HTTPS access to api.fda.gov. The bundled scripts use only the Python standard library. No key is needed, but the anonymous quota is 1000 requests/day; set OPENFDA_API_KEY (free, from open.fda.gov) to raise it to 120000/day. Data is public domain (CC0). FAERS publishes quarterly and lags by three months or more. |
| metadata | {"version":"1.0","skill-author":"K-Dense Inc.","openclaw":{"emoji":"🏛️","homepage":"https://open.fda.gov","envVars":[{"name":"OPENFDA_API_KEY","required":false,"description":"Free openFDA key; raises the daily quota from 1000 to 120000 requests."}]},"hermes":{"category":"research"}} |
openFDA
The FDA's own post-market record, served as a public REST API: 20.6 M adverse-event reports,
every drug application since 1939, and the full text of approved labels. It answers the question
that comes after the biology — what has already happened to this molecule, or to its class, in
people — and it is the cheapest safety evidence available anywhere.
Base URL: https://api.fda.gov — REST, no key required.
Docs: open.fda.gov/apis ·
field reference
Checked against: the live API, August 2026; FAERS data current to 2026-07-30.
Read references/api-reference.md before writing a query by hand,
references/endpoint-fields.md before trusting a field name, and
references/disproportionality.md before reporting any signal
— that one is judgement, not syntax.
The three scripts
| Script | Answers |
|---|
fda_adverse.py | What has been reported against this drug, and is any of it disproportionate? |
fda_approvals.py | When was it approved, by whom, and how many indications has it gained? |
fda_labels.py | What does the approved label actually say? |
Zero results arrive as HTTP 404
This is the single thing to get right. A search that matches nothing returns:
HTTP 404 {"error": {"code": "NOT_FOUND", "message": "No matches found!"}}
That is a successful query with an empty result set. Any client that treats non-200 as failure
turns "this drug has no reports" into a crash, and — worse — makes a typo indistinguishable from
a real zero, because a misspelled field name also returns 404. get() in
scripts/_common.py converts NOT_FOUND into an empty payload; when a count comes back empty,
check the field name against references/endpoint-fields.md before believing it.
The other two surprises: limit above 1000 returns 403 API_KEY_MISSING (a key raises the
daily quota, not the per-request cap — lower limit instead), and is hard-capped at
, so a search matching 500 000 reports has 25 000 reachable records. Partition by
to go deeper.