Recipe: Drug label and shortage lookup

The task

Someone needs two things about a drug at once: what the FDA-approved label actually says (indications, boxed warnings, contraindications), and whether it’s currently listed in a national shortage — a common pairing for “can my patient get this, and what do I need to watch for if they do.”

Tools used: fda_drug_labels, fda_drug_shortages. Two calls, run in parallel.

Copy-paste prompt

For "<drug name>", use Pipeworx to (1) pull the current FDA label — indications, boxed
warning if any, and key contraindications — and (2) check the FDA Drug Shortages database
for its current status. If the shortage database has no entry, tell me explicitly whether
that means "no shortage on record" or "this exact name didn't match anything" — don't
just say "not in shortage."

What a good answer looks like

fda_drug_shortages({ drug: "hydromorphone", status: "Current" })

returns (live call, 2026-08-10 — trimmed to 1 of 26):

{
  "query": { "drug": "hydromorphone", "manufacturer": null, "status": "Current", "advanced": null },
  "total": 26,
  "returned": 20,
  "shortages": [
    {
      "generic_name": "Hydromorphone Hydrochloride Injection",
      "manufacturer": "Hospira, Inc., a Pfizer Company",
      "status": "Current",
      "availability": "Available",
      "presentation": "Hydromorphone Hydrochloride, Injection, 500 mg/50 mL (10 mg/mL) (NDC 0409-2634-50)",
      "update_date": "2026-08-07"
    }
  ]
}

paired with:

fda_drug_labels({ query: 'openfda.generic_name:"HYDROMORPHONE HYDROCHLORIDE"', limit: 1 })
// → indications_and_usage, boxed/other warnings, dosage, contraindications

A trustworthy answer has:

  • a total count on the shortage side that’s distinct from returned (how many rows came back this call) — a caller who only reads shortages.length can undercount
  • each shortage record’s own status field (Current, Resolved, or To Be Discontinued) — not just “found something, must be short”
  • the label’s boxed_warning field surfaced explicitly when present — it’s the single highest-severity FDA safety signal and easy to bury under indications_and_usage

The plausible-sounding failure: total: 0 on the shortage side reads as “definitely not in shortage,” but it can mean three very different things, and the response looks identical for all three:

  1. Genuinely never listed. fda_drug_shortages({ drug: "ibuprofen" })total: 0. Ibuprofen has no FDA national-shortage history under this name — a real, correct negative.
  2. Was in shortage, now resolved — but only visible if you don’t filter by status. fda_drug_shortages({ drug: "rifapentine" }) (no status filter) → total: 1, with "status": "Resolved", "resolved_note": "Available". Re-run the same query with status: "Current" and you get total: 0 — correct in isolation (“not short right now”), but if that’s all you show the caller, you’ve silently dropped “this drug had a shortage as recently as 2026-08-06.”
  3. Name mismatch, not a real negative. fda_drug_shortages({ drug: "Tylenol" })total: 0, even though Tylenol/acetaminophen products do appear in the shortage database under other presentations. The shortage search matches generic_name, openfda.generic_name, and openfda.brand_name as substrings — a brand name that isn’t indexed the way you typed it returns zero, not an error.

Never report “<drug> is not in shortage” from a bare total: 0 without stating which of these three you actually checked for.

Step-by-step tool calls

1. Get the canonical generic name from the label first

fda_drug_labels({ query: 'openfda.brand_name:"TYLENOL"', limit: 1 })
// → generic_name: "ACETAMINOPHEN" (from the label's own openfda block)

Searching the shortage database with the name the label itself reports reduces the name-mismatch failure mode above — though it doesn’t eliminate it, since shortage records key off the specific marketed presentation (tablet vs. injection vs. combination product), not just the active ingredient.

2. Check current shortage status

fda_drug_shortages({ drug: "<generic name>", status: "Current" })

Read total, not just shortages.lengthtotal is the full count, returned is what this page actually contains (capped at limit, default 20).

3. If total: 0, re-check without the status filter before reporting “no shortage”

fda_drug_shortages({ drug: "<generic name>" })

If this also returns total: 0, you have case 1 (genuinely never listed) — a real negative, safe to report. If it returns total > 0 with status: "Resolved" or "To Be Discontinued", you have case 2 — report the history, not just the current snapshot.

4. Pull recent shortage-list activity for context

fda_shortage_changes({ status: "Current", days: 30, limit: 10 })
// → newest-first list of shortage records updated in the last 30 days

Useful for “what’s newly short” rather than “is this one drug short” — sort by update_date, not initial_posting_date, since a long-running shortage gets update_type: "Reverified" on a rolling basis without being new.

Caveats

  • This is FDA national shortage status, not local pharmacy inventory. A drug can show status: "Current" nationally while a specific pharmacy has stock, or show no national shortage while a specific region is out. Say so — don’t let “not in national shortage” read as “your pharmacy definitely has it.”
  • FDA shortage fields are sparse. shortage_reason and resolved_note are often absent even on real records — don’t treat their absence as informative.
  • Label publication trails approval. A just-approved drug may have no label yet in this dataset; that’s a timing gap, not a data-quality problem.
  • Shortage search is substring matching across three fields, not exact-match against a canonical drug identity. A combination product search (e.g. “acetaminophen”) can pull in unrelated combination drugs (e.g. acetaminophen/oxycodone) alongside the plain ingredient — read generic_name on each returned row rather than assuming every hit is the single-ingredient product you meant.
  • No drug-drug or drug-food interaction tool. Same gap noted in the drug safety profile recipe — the label’s warnings text is prescriber prose, not a pairwise interaction check.

Last reviewed August 10, 2026