NDC Lookup API: Get Drug Names, Ingredients, and Package Data in Seconds
Every healthcare app that touches medications needs NDC data. Here's how to look up drug products, search by name or ingredient, and enrich claims with structured drug info — with working TypeScript code.

Every system that processes prescriptions, pharmacy claims, or medication records eventually hits the same problem: you have an NDC code, but you need the drug name, strength, route, and whether it's still active. The FDA publishes this data, but it's spread across multiple downloads, updated on unpredictable schedules, and requires parsing fixed-width files from the 1990s.
This tutorial shows how to look up, search, and batch-process NDC data using FHIRfly's API and TypeScript SDK. You'll have working code in under 5 minutes.
What's an NDC?
The National Drug Code (NDC) is the universal identifier for drugs in the US market. Every drug product and package gets a unique 10- or 11-digit code assigned by the FDA. An NDC encodes three things:
- Labeler (manufacturer/distributor) — first 4-5 digits
- Product (drug formulation) — middle 3-4 digits
- Package (container size/type) — last 1-2 digits
FHIRfly's NDC database covers 300,000+ active and historical codes, updated daily from the FDA Drug Registration and Listing System (DRLS).
Setup
npm install @fhirfly-io/terminology
import { Fhirfly } from "@fhirfly-io/terminology";
const fhirfly = new Fhirfly({ apiKey: process.env.FHIRFLY_API_KEY! });
Get a free API key from the FHIRfly dashboard — 10,000 requests/month included.
Look Up a Single NDC
The most common operation: you have an NDC from a claim or prescription, and you need the drug details.
const result = await fhirfly.ndc.lookup("0069-0151-01", {
shape: "standard",
});
console.log(result.data.brand_name);
// "Lipitor"
console.log(result.data.generic_name);
// "Atorvastatin Calcium"
console.log(result.data.dosage_form);
// "TABLET, FILM COATED"
console.log(result.data.strength);
// "10 mg"
console.log(result.data.route);
// ["ORAL"]
console.log(result.data.is_active);
// true
NDC codes come in several formats — hyphenated (0069-0151-01), plain 10-digit (0069015101), or 11-digit (00069015101). The API normalizes all formats automatically.
Response Shapes
Three shapes control how much data you get back:
| Shape | Fields | Best for |
|---|---|---|
compact | Name, generic, labeler, active status | Autocomplete, lists |
standard | + Brand name, strength, dosage form, route, RxCUI, FHIR coding | Detail views, enrichment |
full | + Active ingredients, DEA schedule, marketing category, pharm classes, contraindications | Compliance, clinical decision support |
FHIR-Ready Coding
Every response includes a pre-built FHIR coding you can drop directly into a MedicationRequest or MedicationStatement:
const result = await fhirfly.ndc.lookup("0069-0151-01", { shape: "standard" });
console.log(result.data.fhir_coding);
// {
// system: "http://hl7.org/fhir/sid/ndc",
// code: "0069-0151-01",
// display: "Lipitor 10 mg Oral Tablet"
// }
No more assembling display strings manually.
Search by Drug Name or Ingredient
When users type a drug name into your app — or when you need to find all formulations of a medication — use the search endpoint:
const results = await fhirfly.ndc.search(
{ q: "metformin", dosage_form: "TABLET", is_active: true },
{ limit: 10 }
);
console.log(`Found ${results.total} active metformin tablets`);
for (const drug of results.items) {
console.log(`${drug.name} — ${drug.labeler}`);
}
// "Metformin Hydrochloride 500 mg — Teva Pharmaceuticals"
// "Metformin Hydrochloride 850 mg — Mylan Pharmaceuticals"
// "Metformin Hydrochloride 1000 mg — Aurobindo Pharma"
// ...
Search Filters
Combine text queries with structured filters to narrow results:
// Find all NDCs for a specific ingredient
await fhirfly.ndc.search({ ingredient: "lisinopril", is_active: true });
// Search by brand name
await fhirfly.ndc.search({ brand: "Humira" });
// Filter by DEA schedule (controlled substances)
await fhirfly.ndc.search({ q: "oxycodone", dea_schedule: "cii" });
// Find injectables from a specific manufacturer
await fhirfly.ndc.search({
labeler: "Pfizer",
route: "INTRAVENOUS",
dosage_form: "INJECTION",
});
// Sort by name for consistent ordering
await fhirfly.ndc.search(
{ generic: "amoxicillin" },
{ sort: "name" }
);
Pagination
let page = 1;
let hasMore = true;
while (hasMore) {
const results = await fhirfly.ndc.search(
{ labeler: "AbbVie", is_active: true },
{ limit: 50, page }
);
for (const drug of results.items) {
await processDrug(drug);
}
hasMore = results.has_more;
page++;
}
Batch Lookups
Processing a pharmacy claims file? Use the batch endpoint instead of making hundreds of individual calls:
const response = await fhirfly.ndc.lookupMany(
["0069-0151-01", "0074-3799-01", "0000-0000-00"],
{ shape: "standard" }
);
for (const result of response.results) {
if (result.status === "ok") {
console.log(`${result.input}: ${result.data.brand_name} (${result.data.generic_name})`);
} else {
console.log(`${result.input}: ${result.status} — ${result.error}`);
}
}
// "0069-0151-01: Lipitor (Atorvastatin Calcium)"
// "0074-3799-01: Humira (Adalimumab)"
// "0000-0000-00: not_found — NDC not found in FDA DRLS"
Batch accepts up to 500 NDC codes per request. Each result includes its own status, so a single invalid code doesn't break the whole batch.
Enrichment: Drug Classes and SNOMED Mappings
The standard and full shapes include enrichment data derived from RxNorm crosswalks:
const result = await fhirfly.ndc.lookup("0069-0151-01", { shape: "full" });
// Drug classes (via RxNorm → RxClass)
console.log(result.data.drug_classes);
// [{ class_id: "N0000175557", class_name: "HMG-CoA Reductase Inhibitors", type: "MOA" }]
// Active ingredients with strength
console.log(result.data.active_ingredients);
// [{ name: "ATORVASTATIN CALCIUM", strength: "10", unit: "mg" }]
// SNOMED CT mappings
console.log(result.data.snomed);
// [{ concept_id: "373444002", term: "Atorvastatin", map_type: "substance" }]
This is valuable for clinical decision support — you can check drug classes without maintaining your own crosswalk tables.
REST API (Without the SDK)
Working in Python, Go, or another language? The REST API is straightforward:
# Single lookup
curl -H "x-api-key: $FHIRFLY_API_KEY" \
"https://api.fhirfly.io/v1/ndc/0069-0151-01?shape=standard"
# Search
curl -H "x-api-key: $FHIRFLY_API_KEY" \
"https://api.fhirfly.io/v1/ndc/search?q=metformin&dosage_form=TABLET&is_active=true&limit=10"
# Batch
curl -X POST -H "x-api-key: $FHIRFLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"codes": ["0069-0151-01", "0074-3799-01"]}' \
"https://api.fhirfly.io/v1/ndc/_batch?shape=standard"
Common Use Cases
| Use Case | Approach |
|---|---|
| Enrich pharmacy claims | Batch lookup with standard shape |
| Drug autocomplete UI | Search with compact shape, limit: 5 |
| Check controlled substance status | Lookup with full shape, read dea_schedule |
| Build FHIR MedicationRequest | Lookup, use fhir_coding field directly |
| Find generic equivalents | Search by generic name, filter is_active: true |
| Validate NDC on a claim | Batch lookup, check for not_found status |
Data Freshness
FHIRfly syncs from the FDA daily. Every response includes legal and attribution metadata, and the full shape includes detailed provenance:
const result = await fhirfly.ndc.lookup("0069-0151-01", { shape: "standard" });
console.log(result.meta.legal);
// { license: "Public Domain", source_name: "FDA NDC Directory", ... }
console.log(result.meta.shape);
// "standard"
NDC data from the FDA is public domain — no licensing restrictions on what you build.
Key Takeaways
- 300K+ NDC codes covering active and historical drug products and packages
- Three response shapes — fetch only what you need
- FHIR coding included — drop directly into FHIR resources
- Batch endpoint — process up to 500 codes per request
- Enrichment data — drug classes, SNOMED mappings, and contraindications via RxNorm
- Daily sync from the FDA with provenance on every response
Next Steps
- Get a free API key from the FHIRfly dashboard
- Install the SDK:
npm install @fhirfly-io/terminology - Try a lookup with your own NDC codes
- Check the NDC API docs for the complete parameter reference
Related Posts
Written by The FHIRfly Team — a collective of healthcare data experts, AI specialists, and industry veterans building better clinical coding APIs.