API Reference

REST API

A structured, versioned API for querying the full TwinFyRx drug intelligence platform. All endpoints return JSON and follow consistent patterns for pagination, errors, and resource nesting.

Setup

Authentication & Access Tiers

TwinFyRx uses a tiered access model. During the evaluation period, data endpoints are openly accessible — no key required. Once a license is activated per customer, those endpoints require an X-API-Key header. A wrong key always returns 401.

SurfaceAccessPaths
Always publicNo key, ever/v1/demo/*
/v1/data-quality/*
/v1/metadata/*
/v1/fhir/*
/health*
Licensed surfacesOpen now; key-gated once license is active/v1/drugs/*
/v1/pricing/*
/v1/formulary/*
/v1/diseases/*
/v1/ndc/*
/v1/atc/*
/v1/medicare/*
/v1/pharmacies/*

Once you have a key, include it on every request to the licensed surfaces:

curl -H "X-API-Key: your_api_key" \
  https://api.twinfyrx.com/v1/drugs/search?q=atorvastatin

Key provisioning: One key per customer, scoped to the licensed tier. Keys are issued during onboarding and rotated on request. Request access to get started.

Backwards compatibility: The drug_id primary key, all enum values, and the v1 path prefix are stable. Breaking changes will be versioned under a new path prefix with a minimum six-month migration window.

Setup

Base URL

https://api.twinfyrx.com

All endpoints are versioned under /v1.

Setup

Response Headers

Every response carries three diagnostic headers:

HeaderValueNotes
X-Schema-Version1.0Schema version in effect. Increments on breaking changes.
X-Data-As-Of2026-04-28T14:32:00ZUTC timestamp of the most recent data sync to MotherDuck.
X-Request-IDuuid-v4Echo of client-supplied X-Request-ID, or a server-generated UUID. Include in support tickets.

Supply your own X-Request-ID on outbound calls to correlate requests across your own logs. X-Schema-Version and X-Data-As-Of are exposed via CORS so browser clients can read them.

Setup

Error Handling

All error responses follow a consistent structure. The request_id field matches the X-Request-ID header and is the primary reference for support:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Drug with rxcui 999999 not found",
    "request_id": "a3f2c1d8-7b4e-4e2a-9c1f-0d5e8a3b2f91"
  }
}
StatusCodeMeaning
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDResource not found
422VALIDATION_ERRORInvalid query parameters
500INTERNAL_ERRORUnexpected server error
Core

Drugs

Search, retrieve, and explore the drug concept hierarchy. Every response anchors to a canonical RxNorm drug concept.

GET/v1/drugs/search

Search drugs by name, ingredient, or brand name. Returns paginated results.

Parameters

qstringREQUIREDSearch query (min 2 characters)
limitintegerResults per page (1–100, default 20)
offsetintegerPagination offset

Response

results[]DrugSummaryArray of matching drugs
.rxcuiintegerRxNorm concept ID (drug_id)
.drug_namestringFull clinical drug name
.ingredientstringActive ingredient(s)
.is_genericbooleanWhether this is a generic concept
totalintegerTotal matching results

Example Response

{
  "results": [
    {
      "rxcui": 617314,
      "drug_name": "atorvastatin 20 MG Oral Tablet",
      "ingredient": "atorvastatin",
      "dose_form": "Oral Tablet",
      "clinical_drug_form": "atorvastatin Oral Tablet",
      "brand_name": null,
      "is_generic": true
    }
  ],
  "total": 12,
  "limit": 20,
  "offset": 0
}
GET/v1/drugs/{rxcui}

Full drug detail including RxNorm hierarchy, therapy attributes, and branded variants.

Parameters

rxcuiintegerREQUIREDRxNorm concept ID (path parameter)

Response

rxcuiintegerDrug concept ID
drug_namestringFull drug name
ingredient_rxcuiintegerIngredient concept ID
clinical_drug_form_rxcuiintegerDrug form concept ID
therapy_patternstringTherapy behavior enum
specialty_flagbooleanSpecialty drug indicator
benefit_channelstringPharmacy, medical, or dual
GET/v1/drugs/{rxcui}/icd10-volumes

Utilization-weighted drug-to-diagnosis mappings with percent volume estimates.

Response

drugDrugSummaryDrug summary object
is_single_indication_drugbooleanWhether drug maps to a single diagnosis
icd10_volumes[]ICD10VolumeDiagnoses sorted by volume
.icd10_codestringICD-10-CM code
.pct_volumedecimalEstimated % of prescriptions for this diagnosis
.is_dominant_indicationbooleanWhether this is the primary indication
GET/v1/drugs/{rxcui}/suspecting-rules

All active suspecting rules for a drug. Each rule contains structured JSON logic for execution.

Response

drugDrugSummaryDrug summary
rule_countintegerTotal rules returned
rules[]SuspectingRuleArray of executable rules
.rule_categorystringprescriber_specialty, concurrent_rx, compound, etc.
.rule_strengthstringstrong_prior, weak_prior, or exclusion
.rule_logicobjectStructured logic for SQL generation
.confidencedecimalBase confidence score (0–1)
Market Intelligence

Pricing

NADAC acquisition costs (weekly cadence) and Medicare Part B ASP payment limits (quarterly). Both resolve through the drug concept hierarchy.

GET/v1/drugs/{rxcui}/pricing

Current pricing snapshot — latest NADAC week and latest ASP quarter for a drug.

Response

drugDrugSummaryDrug summary
nadacNADACSnapshot | nullLatest NADAC pricing (if available)
.median_per_unitdecimalMedian acquisition cost per unit
.pricing_unitstringUnit label (e.g., 'EACH', 'ML')
aspASPSnapshot | nullLatest ASP pricing (if available)
.median_payment_limitdecimalMedian Part B payment limit
GET/v1/drugs/{rxcui}/nadac

Historical NADAC pricing with weekly granularity. Defaults to 2 years of history.

Parameters

startdateStart date (YYYY-MM-DD, default: 2 years ago)
enddateEnd date (YYYY-MM-DD, default: today)

Response

pricing_unitstringUnit of measure
weeks[]NADACWeekWeekly pricing data points
.as_of_datedateEffective date
.median_per_unitdecimalMedian cost per unit
.ndc_countintegerNDCs contributing to this aggregate

Example Response

{
  "drug": { "rxcui": 617314, "drug_name": "atorvastatin 20 MG Oral Tablet" },
  "pricing_unit": "EACH",
  "weeks": [
    { "as_of_date": "2026-03-05", "median_per_unit": 0.0412, "min_per_unit": 0.0389, "max_per_unit": 0.0445, "ndc_count": 14 },
    { "as_of_date": "2026-02-26", "median_per_unit": 0.0415, "min_per_unit": 0.0391, "max_per_unit": 0.0448, "ndc_count": 14 }
  ]
}
GET/v1/drugs/{rxcui}/asp

Historical ASP (Medicare Part B) payment limits by quarter with HCPCS code mappings.

Response

quarters[]ASPQuarterQuarterly ASP data points
.effective_quarterstringe.g., '2026Q1'
.median_payment_limitdecimalMedian payment limit per unit
.hcpcs_codesstring[]Associated HCPCS codes
Reference

Diagnoses

Search and explore ICD-10-CM diagnoses with reverse drug mappings — find which drugs are most commonly prescribed for a given condition.

GET/v1/diagnoses/search

Search ICD-10 diagnoses by code or description text.

Parameters

qstringREQUIREDICD-10 code or description text
limitintegerResults per page (default 20)

Response

results[]DiseaseSummaryMatching diagnoses
.icd10_codestringICD-10-CM code
.diagnosisstringDiagnosis description
.is_billablebooleanWhether this is a billable code
GET/v1/diagnoses/{icd10_code}

Full diagnosis detail including ICD-10 hierarchy and top 20 drugs prescribed for this condition.

Response

icd10_codestringICD-10-CM code
diagnosisstringFull description
chapter_namestringICD-10 chapter
is_billablebooleanBillable indicator
top_drugs[]DrugForDiseaseTop 20 drugs by prescribing volume
.pct_volumedecimalEstimated share of prescriptions
Reference

Classification & Identifiers

ATC therapeutic classification hierarchy and NDC identifier resolution.

GET/v1/atc/search

Search ATC classification codes by code or name.

Parameters

qstringREQUIREDATC code or therapeutic class name
GET/v1/atc/{atc_code_5}

Full 5-level ATC hierarchy for a given code.

Response

atc_code_1 → atc_code_5stringAll 5 ATC hierarchy levels
atc_name_1 → atc_name_5stringNames for each level
GET/v1/drugs/{rxcui}/atc

All ATC classifications for a drug concept.

GET/v1/ndc/{ndc_code}

Resolve an NDC code to its drug concept with therapy attributes and specialty flags.

Response

ndcstringInput NDC code
rxcuiintegerResolved drug concept ID
drug_namestringDrug name
therapy_patternstringTherapy behavior classification
specialty_flagbooleanSpecialty drug indicator
Patterns

Pagination

List endpoints return a consistent envelope. The response also carries an X-Total-Count header with the untruncated count, useful for building UI paginators without parsing the body:

{
  "results": [ ... ],
  "total": 142,
  "limit": 20,
  "offset": 0
}

# Response header:
X-Total-Count: 142
RuleDetail
Max limit1000 results per request. Default is 20.
Offset pagingUse limit + offset for result sets up to ~10,000 rows.
Bulk endpointPOST /v1/drugs:lookup accepts up to 500 rxcuis per call — preferred over looping single-drug GETs.
Patterns

Rate Limits

Rate limits are enforced per API key. Specific limits are communicated during onboarding and vary by tier. When a limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.

HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-Request-ID: a3f2c1d8-7b4e-4e2a-9c1f-0d5e8a3b2f91

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 30 seconds.",
    "request_id": "a3f2c1d8-7b4e-4e2a-9c1f-0d5e8a3b2f91"
  }
}

Recommended retry strategy: exponential backoff starting at 1 second, capped at 60 seconds, with jitter. For batch workloads, use POST /v1/drugs:lookup to reduce request volume — 500 drugs in one call instead of 500 individual GETs.