Drug formulary CSV import API

drug_formulary_v1

mediumFHIR · Medication6 fields · 2 required · 3 validatedPack · Healthcare

Import this template via API. Import a drug formulary from CSV. ATC-coded, GTIN-checksum-validated, Pharmacode-aware, emits FHIR Medication.

30-second curl

curl -X POST https://api.adaptivmapr.com/v1/uploads \
  -H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
  -F "template=drug_formulary_v1" \
  -F "file=@your_data.csv"
phi-cloud bundle required for full-data mode on this template. Schema-only mode (headers + ≤3 sample rows) is free and always available. Activate the bundle →

At a glance

Pack
Healthcare
FHIR resource
Medication
Risk level
medium
Fields
6 (2 required, 3 validated)

Why this template?

The Drug formulary template is the canonical schema for a pharmacy's medication catalog. Each row emits a FHIR Medication resource — the ATC code lands in Medication.code with the WHO ATC coding system, the GTIN goes into Medication.identifier with the GS1 system URI, and the Swiss Pharmacode (4-7 digits) carries the local registry id. The template is `medium` risk not because it contains PHI — drugs are not patients — but because dosage-form and strength errors are downstream-dangerous; a transposed digit in a strength column produces a 100x dose error in the resulting prescription system. AdaptivMapr validates ATC against the published pattern (^[A-Z]NN[A-Z]{2}NN$), GTIN against the GS1 mod-10 checksum, and Pharmacode against the 4-7 digit shape. Customers use this template when seeding an e-prescribing system, when standardising an in-house pharmacy database, or when re-importing after a vendor migration.

GTIN supports 8 / 12 / 13 / 14 digit shapes (EAN-8, UPC-A, EAN-13, GTIN-14) with mod-10 checksum verification — the same algorithm as ITF-14 barcodes. ATC five-level codes (anatomical → therapeutic → pharmacological → chemical → substance) all validate against the same regex. Pharmacode is Swiss-specific and not enforced as a checksum because the algorithm is proprietary.

Migration scenarios & common foreign headers

Migration scenarios for the Drug formulary: seeding a new e-prescribing module with a clinic's in-house formulary, importing a hospital pharmacy's catalogue after a procurement-system switch, quarterly refreshes against Swissmedic / EMA / FDA bulletins, and consolidating multiple regional formularies after a healthcare-network acquisition. Foreign headers we routinely see: "ATC / Wirkstoffcode / Code ATC / GTIN / EAN / Barcode / Codice / Pharmacode / Pharma-Code / Präparat / Préparation / Medicamento / Farmaco / Darreichungsform / Forme galénique / Forma farmacéutica / Stärke / Dosage / Dosis". Trade names rarely match ATC patterns directly, so the resolver layer carries weight on this template — most imports rely on the high-confidence trade-name → ATC fallback to clear without manual intervention.

Schema

The canonical column set, with the type each row carries, whether it is required, the field-level validators that fire on commit, and the multilingual header hints the cascade resolves against.

ColumnTypeRequiredValidatorsHints
atc_codestringyesatc_codeatc · wirkstoffcode
gtinstringgtingtin · ean · barcode
pharmacodestringpharmacodepharmacode · pharma-code
namestringyespräparat · préparation · medicamento
dosage_formstringdarreichungsform · forme galénique · forma
strengthstringstärke · dosage · dosis

How AdaptivMapr maps your headers to this template

Five layers run in order, cheapest first. Layer 1 (Statistics) auto-accepts headers that have been mapped the same way across past uploads. Layer 2 (Heuristic) compares your header to the column name, the optional label, and every registered hint (DE / FR / IT / EN / ES) after a Unicode-and-punctuation-normalising pass. Layer 3 (Fuzzy) catches typos and reordered words. Layer 4 (Semantic) uses cached embeddings to catch the long tail of paraphrases. Layer 5 (LLM) only fires on genuinely ambiguous columns, constrained to the template’s allowed column set so it cannot invent a field. When a layer auto-accepts, the lower-cost layers below it never run — that is the cost lever.

REST · POST /v1/uploads

Pass the template_id; the cascade picks up the rest.

curl -X POST https://api.adaptivmapr.com/v1/uploads \
  -H "Authorization: Bearer $ADAPTIVMAPR_API_KEY" \
  -F "template=drug_formulary_v1" \
  -F "file=@your_data.csv"

The canonical template definition is read-only at GET /v1/templates/drug_formulary_v1.

MCP · Cursor / Claude Desktop

Drop AdaptivMapr into your IDE. Schema-only calls are free and unlimited.

// In Cursor or Claude Desktop with the AdaptivMapr MCP server installed:
adaptivmapr.match_headers({
  template: "drug_formulary_v1",
  headers: ["atc_code", "gtin", "pharmacode", "name"]
})
MCP install instructions →

FAQ — Drug formulary CSV import

Does AdaptivMapr resolve trade names to ATC codes?

Yes — the ATC validator falls back to a resolver that maps trade names ("Aspirin", "Dafalgan") to ATC codes when the direct validator fails, and the substitution commits when confidence ≥ 0.85.

What about controlled-substance schedules?

Add a `schedule` field via a fork. The canonical template stays jurisdiction-neutral because controlled-substance lists differ per country.

Can I import a formulary with mixed CH (Pharmacode) and EU (GTIN) products?

Yes — Pharmacode and GTIN are both optional. The minimum is ATC + name; the rest enrich the row.

Are dosage_form and strength validated as free text?

Yes. The lexicon is too large and too localised to enum-bound; teams with strict downstream systems usually post-process these fields against an internal lookup.

Keep exploring

Browse other templates in the Healthcare pack

Drug formulary CSV import API — AdaptivMapr — AdaptivMapr