NCPDP

Read a pharmacy claim or an ePrescription in one line.

@cosyte/ncpdp handles both NCPDP standards in one package: Telecom pharmacy claims and SCRIPT ePrescribing messages. Vendor quirks become positioned warnings, and money and quantities are handled as strings, so a float never touches a paid amount.

@cosyte/ncpdp
npm install @cosyte/ncpdp

Need it integrated? Talk to us.

The standard

NCPDP is two standards: one for claims, one for prescriptions.

  • NCPDP's Telecommunication Standard is a format for submitting third-party drug claims and related transactions between pharmacies, insurers and administrators, including eligibility checks, billing and prior authorization. Source: NCPDP, Access to Standards
  • The SCRIPT standard carries prescription information between prescribers, pharmacies and payers: new prescriptions, changes, refill requests, cancellations, medication history and electronic prior authorization. Source: NCPDP, Access to Standards
  • Under HIPAA, Telecommunication Standard version D.0 is the retail pharmacy claims standard through August 14, 2027, and version F6 on and after April 14, 2028. Both are adopted in between. Source: 45 CFR 162.1102, 2025 edition (govinfo)
  • For Medicare Part D, CMS requires NCPDP SCRIPT version 2023011 for e-prescribing beginning January 1, 2028, retiring version 2017071. Source: CMS, e-prescribing adopted standard

@cosyte/ncpdp

Two unrelated wire formats, one careful reader.

The implementation guides for both standards are purchased products, so the usual route is a hand-rolled reader: an XML walk for SCRIPT and a split on control characters for Telecom. That works until real input arrives. This package is the other choice.

  • Telecom: build, serialize and parse pharmacy claims, with the control-character framing and fixed-position fields handled for you.
  • SCRIPT: parse and build ePrescribing XML such as NewRx, RxRenewal and RxChange.
  • A lenient reader: a vendor quirk becomes a positioned warning, never an exception in the middle of a dispense.
  • A conservative emitter that only writes spec-clean output.
  • Money and quantities handled string-wise, so binary floating point cannot corrupt a value.
  • Built-in profiles for Surescripts SCRIPT and PBM Telecom traffic, written with the same public defineProfile() API you have.
  • A conformance statement that names each standard version it decodes.
telecom-claim.jsjs
import { buildTelecomRequest, serializeTelecom, parseTelecom, claim } from "@cosyte/ncpdp/telecom";

// Emit a spec-clean Telecom B1 billing claim. Every value below is synthetic.
const wire = serializeTelecom(
  buildTelecomRequest({
    header: { transactionCode: "B1", binNumber: "999999", dateOfService: "20260115" },
    segments: [
      { segmentId: "04", fields: [{ id: "C2", value: "SYNTHCARD09" }] },
      {
        segmentId: "07",
        fields: [
          { id: "D2", value: "RX0000001" },
          { id: "E1", value: "03" },
          { id: "D7", value: "99999999999" },
          { id: "E7", value: "30000" },
          { id: "D5", value: "30" },
        ],
      },
    ],
  }),
);

// Read it back. A vendor quirk becomes a positioned warning here, never a throw.
const t = parseTelecom(wire);
const c = claim(t);

console.log(t.kind, t.header.transactionCode, t.warnings.length);
console.log(c?.cardholderId, c?.prescriptionReferenceNumber);
console.log(c?.product?.id, c?.product?.qualifier);
console.log(c?.quantityDispensed?.source, c?.quantityDispensed?.impliedDecimal);

From the @cosyte/ncpdp README on GitHub, verbatim. Every value in it is synthetic.

Limits

What it does not do.

Its README names the gaps rather than leaving them silent:

  • Electronic Prescribing of Controlled Substances is out of scope.
  • Parsing and emitting are whole-message only; there is no streaming mode.
  • The SCRIPT builder emits the SIG it is given and generates none. The structured SIG view is lossy by design; the free text stays authoritative.
  • Most wire-code labels do not ship, because no public source establishes them.
  • No third party has tested it, and there is no differential corpus against a reference implementation.
  • The SCRIPT side has one runtime dependency, fast-xml-parser, configured with entity resolution disabled.

The full status and limits, in the README

Alternatives

What else you could use.

Each description comes from the project’s own documentation or listing, linked below.

E-prescribing network

Surescripts

The network pharmacists and prescribers use to exchange NCPDP-defined transactions such as NewRx, RxChange, RxRenewal and CancelRx. A library formats and reads the messages; a network delivers them.

Source: Surescripts, E-Prescribing

Pharmacy claims switch

Redsail PowerLine

A claims switch that receives NCPDP transactions, sends them on to processors and returns the responses to the pharmacy.

Source: Redsail Technologies, PowerLine

EDI toolkit

EdiFabric

A toolkit for translating EDI inside your own applications, covering ten EDI standards, NCPDP among them.

Source: EdiFabric

Works with

  • X12Medical claims, remittance and eligibility use X12: @cosyte/x12.
  • De-identification@cosyte/deid applies a HIPAA Safe Harbor policy to an NCPDP Telecom transaction. SCRIPT is not supported.
  • @cosyte/synthGenerates synthetic SCRIPT messages and Telecom claims for your tests.

Try @cosyte/ncpdp on your own messages.

It is free and MIT-licensed. If it saves you a day, a star on GitHub helps other engineers find it.

Need it integrated? Talk to us, or see what our integration services cover.