Blog
RxNorm API Tutorial: Drug Name Resolution for Developers
A step-by-step developer tutorial for using the NLM RxNorm API to resolve drug names to RxCUI identifiers. Covers exact match, normalized match, and fuzzy approximate matching with curl examples and JavaScript code. Explains how RxLabelGuard uses RxNorm internally for reliable drug resolution.
Why drug name resolution is harder than it looks
A doctor writes 'Lipitor 20mg.' A pharmacy system stores 'atorvastatin calcium 20 MG Oral Tablet.' An EHR database contains NDC code 00071015523. A patient says 'my cholesterol pill.' These all refer to the same drug, but no simple string matching will connect them. Drug name resolution, the process of mapping varied drug inputs to a single canonical identifier, is a prerequisite for any reliable drug interaction checking system.
The challenge extends beyond brand-versus-generic naming. Drug names have multiple valid representations across clinical systems: different salt forms (atorvastatin vs atorvastatin calcium), different dose forms (tablet vs oral tablet), different strengths, and different packaging configurations. A production drug interaction system must handle all of these variations and map them to a consistent identifier that can be used to query interaction data.
RxNorm, maintained by the U.S. National Library of Medicine, is the standard solution for this problem. It provides a normalized naming system for clinical drugs with unique concept identifiers (RxCUI) that serve as the lingua franca for drug identification across healthcare IT systems. The RxNorm API is free, requires no API key, and remains one of the most reliable government health data services available.
RxNorm concepts and identifiers
Before diving into API calls, it helps to understand how RxNorm organizes drug information. RxNorm assigns a unique identifier called an RxCUI (RxNorm Concept Unique Identifier) to each normalized drug concept. These concepts exist at different levels of specificity, called term types.
The most commonly used term types are SCD (Semantic Clinical Drug), which represents a generic drug at a specific strength and dose form like 'atorvastatin 20 MG Oral Tablet,' and SBD (Semantic Branded Drug), which adds the brand name like 'Lipitor 20 MG Oral Tablet.' There are also IN (Ingredient) level concepts like 'atorvastatin,' BN (Brand Name) concepts like 'Lipitor,' and various pack and group level concepts.
For drug interaction checking, you typically want to resolve to the IN (Ingredient) level, because interactions are defined between active ingredients regardless of brand, strength, or dose form. The RxNorm API provides endpoints to navigate between these levels, allowing you to start with any form of drug input and arrive at the ingredient-level RxCUI needed for interaction lookups.
Setting up: base URL and request format
The RxNorm API base URL is https://rxnav.nlm.nih.gov/REST/ and all endpoints return JSON by default when you append .json to the path. No API key is required. The rate limit is 20 requests per second per IP address, which is generous for most development and production use cases.
All requests are GET requests with query parameters. The API uses a straightforward REST design where each endpoint returns a JSON object with a nested structure containing the results. Error handling is simple: if a drug is not found, the relevant field in the response is null or an empty array rather than an HTTP error status.
Step 1: Exact match with findRxcuiByString
The first resolution strategy to try is an exact match using the rxcui endpoint. This works when the input string matches a known RxNorm concept name precisely or very closely.
The curl command is: curl 'https://rxnav.nlm.nih.gov/REST/rxcui.json?name=atorvastatin&search=2'. The search=2 parameter enables normalized matching, which handles minor variations in whitespace, capitalization, and word order. The response includes an idGroup object containing an rxnormId array with matching RxCUI values.
In JavaScript, this looks like a standard fetch call. Make a GET request to the URL, parse the JSON response, and extract the rxnormId value from response.idGroup.rxnormId. If the array is empty or the field is null, the exact match failed and you should fall through to the next resolution strategy.
Exact match works well for standardized inputs like EHR drug dictionaries, barcode-scanned NDC codes (after NDC-to-name mapping), and structured prescription data. It is the fastest resolution path because it requires only a single API call.
Step 2: Normalized match for common variations
When exact match fails, the next strategy is the drugs endpoint, which performs broader matching including ingredient-level resolution. The curl command is: curl 'https://rxnav.nlm.nih.gov/REST/drugs.json?name=lipitor'. This endpoint accepts brand names, generic names, and partial drug descriptions, and returns a richer response structure including the drug concept group with all related concepts.
The response from the drugs endpoint contains a drugGroup object with a conceptGroup array. Each concept group contains drug concepts at different term type levels (IN, SCD, SBD, etc.). For interaction checking, you typically want the IN (Ingredient) term type concept, which gives you the base active ingredient RxCUI.
In JavaScript, parse the response and iterate through conceptGroup entries looking for the tty (term type) value of 'IN'. The rxcui field on the matching conceptProperties entry is the ingredient-level identifier you need. If no IN-level concept is returned, look for SCD or SCDG (Semantic Clinical Drug Group) as fallback term types.
This endpoint handles the brand-to-generic mapping problem cleanly. Searching for 'Lipitor' returns atorvastatin-related concepts with their RxCUI values, without requiring the caller to know that Lipitor is atorvastatin.
Step 3: Fuzzy matching with approximateTerm
For user-typed input, misspellings, and informal drug descriptions, RxNorm provides the approximateTerm endpoint. This performs phonetic and edit-distance matching against the RxNorm vocabulary, returning the closest matches ranked by similarity. The curl command is: curl 'https://rxnav.nlm.nih.gov/REST/approximateTerm.json?term=lisinpril&maxEntries=5'. Note the intentional misspelling of lisinopril: the approximate match endpoint is designed to handle exactly this kind of input.
The response contains a candidate array with each match including the rxcui, score (similarity measure), and rank. Higher scores indicate closer matches. The maxEntries parameter controls how many candidates are returned, with a maximum of 20.
Approximate matching is essential for patient-facing applications and any system that accepts free-text drug input. Users misspell drug names frequently, and the phonetic matching in RxNorm handles most common misspellings. 'Lisinpril' matches 'lisinopril,' 'amoxacillin' matches 'amoxicillin,' and 'metforman' matches 'metformin.'
In JavaScript, sort the candidates by score descending and take the top result. For interactive applications like autocomplete, you might present the top three to five candidates and let the user confirm the correct match. For automated pipelines, taking the top-ranked candidate is usually sufficient, but you should set a minimum score threshold below which you treat the match as uncertain.
NDC code resolution
National Drug Code (NDC) identifiers are commonly encountered in pharmacy systems, insurance claims, and supply chain data. RxNorm provides direct NDC-to-RxCUI mapping through the rxcui endpoint with the idtype parameter. The curl command is: curl 'https://rxnav.nlm.nih.gov/REST/rxcui.json?idtype=NDC&id=00071015523'.
Note that NDC codes come in multiple formats (10-digit, 11-digit, with and without hyphens), and the format used in the API query must match what RxNorm expects. The 11-digit format without hyphens is the most reliable. If your source NDC is in a different format, normalize it to 11 digits by zero-padding each segment before querying.
NDC resolution returns the specific product-level RxCUI (typically SCD or SBD term type). For drug interaction checking, you will need an additional step to navigate from the product level to the ingredient level using the getAllRelatedInfo or getRelatedByType endpoint.
Building a complete resolution pipeline
A production drug resolution pipeline should chain these strategies in a fallback sequence: try exact match first because it is fastest, fall back to normalized match for brand names and common variations, and use approximate match as the last resort for unrecognized input. Each step requires only one API call, so the worst case is three sequential API calls, completing in well under a second.
The pipeline should also normalize the resolved RxCUI to the ingredient level. Use the getAllRelatedInfo endpoint (curl 'https://rxnav.nlm.nih.gov/REST/rxcui/{rxcui}/allrelated.json') to get all related concepts, then extract the IN-level concept. This ensures consistent identifier-level resolution regardless of whether the input was a brand name, generic name, NDC code, or misspelled variant.
Error handling in the pipeline should distinguish between three outcomes: successful resolution (a high-confidence RxCUI match was found), ambiguous resolution (multiple candidates with similar scores), and failed resolution (no match found). Each outcome requires different handling in the consuming application. Successful resolution proceeds to interaction lookup. Ambiguous resolution might prompt the user for clarification. Failed resolution should return an appropriate error rather than silently proceeding with bad data.
How RxLabelGuard uses RxNorm internally
RxLabelGuard's interaction checking pipeline uses this exact resolution strategy internally. When you call the check interactions endpoint with a drug name, the API first resolves the input through RxNorm using the cascading exact, normalized, and approximate match strategy described above. The resolved RxCUI is then used to query openFDA for the corresponding FDA label, and the interaction text from that label is extracted and structured.
This means you do not need to build your own RxNorm resolution pipeline if you are using RxLabelGuard. The API accepts drug names, brand names, generic names, and NDC codes directly, and handles all resolution internally. The resolved RxCUI and drug name are included in the API response so you can see how the input was interpreted.
However, if you are building a system that needs drug name resolution for purposes beyond interaction checking, such as drug formulary lookup, prescription matching, or clinical data normalization, the RxNorm API is an excellent free resource that you should integrate directly. The resolution pipeline described in this tutorial is the same pattern used across healthcare IT for drug identification.
Rate limiting and production considerations
The RxNorm API rate limit of 20 requests per second is per IP address and is not enforced with API keys. For most applications, this is more than sufficient. However, if you are processing batch data with thousands of drug names, you should implement client-side rate limiting to stay within bounds. A simple token bucket or sliding window rate limiter set to 15 requests per second provides adequate headroom.
Caching is highly recommended for production use. Drug name-to-RxCUI mappings change infrequently; the RxNorm vocabulary is updated monthly. Caching resolved RxCUI values with a 24-hour TTL eliminates redundant API calls for commonly queried drugs and dramatically reduces your effective request volume.
The RxNorm API has historically been very reliable, but it is a government service without an SLA. If your application requires guaranteed availability, consider maintaining a local copy of RxNorm data (available for free download from NLM) as a fallback, or use a managed service like RxLabelGuard that handles caching and fallback strategies internally.
Medical disclaimer
This information is derived from FDA Structured Product Labeling and is provided for informational purposes only. It should not be used as a substitute for professional medical advice, diagnosis, or treatment. Always consult a qualified healthcare provider.
References
- RxNorm API (U.S. National Library of Medicine (NLM); accessed Mar 6, 2026)
- RxNav APIs (U.S. National Library of Medicine (NLM); accessed Mar 6, 2026)
- RxNorm Overview (U.S. National Library of Medicine (NLM); accessed Mar 22, 2026)
- openFDA Drug Label Endpoint (U.S. Food and Drug Administration (FDA); accessed Mar 6, 2026)