NCPDP Telecom Format for Mere Mortals

Quick Summary (TL;DR;)

NCPDP (National Council for Prescription Drug Programs) telecommunication standard specifies the format of pharmacy claims and other pharmacy-related transactions.

An NCPDP transaction consists of segments; segments consist of fields; each field contains a single piece of data, such as a name, an identifier, an NDC drug code, or a quantity.

Fields or a group of fields could repeat to express one-to-many relationships. A repeating group is always preceded by a field containing the count of repetitions.

Fields and segments are separated using non-printable ASCII characters.

The NCPDP telecom standard assumes the request-response model where a request contains a single transaction (e.g., a single pharmacy claim). NCPDP provides a related batch standard that specifies how to transmit multiple transactions in a single file. The batch standard defines the format of headers and trailers used to separate transactions.

HIPAA mandates the use of the NCPDP telecom standard (and the related batch standard) for pharmacy drug claim submission.

The NCPDP format could be challenging to understand; the easiest way to parse and view NCPDP files is to use our free online NCPDP viewer.

A Quick Example

Here is a simple claim (so-called “B1” transaction) in NCPDP telecom format with added batch headers. You can view a line-by-line interactive decoding of this example here.

␂00T123456789               2021123456789123456P1234567WPS0000000         ␃
␂G11234567890123456D1B101        1234567890123     202108210000000100	
␞␜AM04␜C2123456789␜CCJANE␜CDDOE␜FOMYPLAN␜C90␜C1GR1␜C3001␜C62	
␞␜AM01␜C419800225␜C52␜CAJANE␜CBDOE␜CM100 MAIN STR␜CNWASHINGTON␜CODC␜CP100010000␜CQ5551234567␝
␞␜AM07␜EM1␜D2000000123456␜E103␜D700003089421␜E70000030000␜D301␜D5030␜D80␜DE20210701␜DJ3␜C800␜DT3␜28EA	
␞␜AM11␜D90000057A␜DC0000027E␜DX0000016B␜DQ00000000␜DU0000084F␜DN07	
␞␜AM03␜EZ01␜DB1234567890␜DREVIL␜PM5557654321␃
␂9920211840000005162END Dyl B1  

Let’s use this example to explore key concepts of the NCPDP format.

Separators

The symbols in the example above, like ␞ and ␜, represent non-printable (hidden) ASCII characters that are used as separators. Normally, you would see spaces instead of these symbols (hence non-printable). In the text above, we replaced the non-printable characters with their symbolic representation. Our NCPDP viewer does it automatically, as well as some text editors.

The two essential separators are ␞ and ␜. ␞ (RS-Record Start) indicates the start of a segment, ␜ (FS-Field Start) marks the start of a field. Surprisingly, there are no “end” separators; a segment or a field ends when we encounter another separator or the end of the file.

␂ (STX) and ␃ (ETX) separators indicate the start/end of transaction headers and trailers. These separators are defined in the NCPDP batch standard.

Note that the new line character (\n) is not a valid separator. In the example above, we put each segment on its own line for readability purposes, but in real life, all segments will be concatenated together in a single line.

Fields

A field starts with the ␜ separator followed by a two-character field identifier. The field’s value immediately follows the identifier.

For example:

␜CNWASHINGTON

CN is the field identifier. We can look up its description in the telecom standard, which gives us “Patient City Address.”

Field IDs consist of two alphanumeric characters, which does not make them very mnemonic. We can only guess that the decision to use only two characters was driven by the desire to minimize the size of NCPDP transactions/messages.

If we were to use JSON, our field would be equivalent to this snippet:

{
  "patient_city_address": "WASHINGTON"
}

Segments

A segment is a group of logically related fields representing a business entity, such as a patient, a claim, or a provider.

A segment starts with the ␞ (RS-Record Start). The segment’s fields follow the separator.

Here is an example of the patient segment consisting of ten fields:

␞␜AM01␜C419800225␜C52␜CAJANE␜CBDOE␜CM100 MAIN STR␜CNWASHINGTON␜CODC␜CP100010000␜CQ5551234567

The first field, ␜AM01, plays a unique role. It communicates a segment identifier. As with fields, the segment identifier consists of two characters. A segment identifier is usually a number, “01” defines the “Patient” segment.

A segment ends when we encounter another segment separator or the end of the file. In the case of a batch file, a segment also ends when we encounter STX/ETX separators.

We can translate our NCPDP snippet into JSON as follows:

{
  "patient" : {
    "date_of_birth" : "1980-02-25",
    "patient_gender_code" : "Female",
    "patient_first_name" : "JANE",
    "patient_last_name" : "DOE",
    "patient_street_address" : "100 MAIN STR",
    "patient_city_address" : "WASHINGTON",
    "patient_state_province_address" : "DC",
    "patient_zip_postal_zone" : "100010000",
    "patient_phone_number" : "5551234567"
  }
}

Transactions

A transaction is a group of segments that convey information related to a single use case, such as a pharmacy claim submission or a claim reversal.

The NCPDP standard defines the list of segments that constitute a transaction. It also specifies what segments are optional and what is required.

Segments do not repeat; that is, there could be only one segment with a given ID within a transaction.

Each NCPDP transaction is assigned a two-character code, such as B1 (claim submission), B2 (claim reversal), etc.

Our example at the beginning of this post represents a single transaction. It consists of several segments: insurance, patient, claim, pricing, and so on.

A transaction must be preceded by a header.

Headers

A transaction header conveys information about the transaction itself. It contains the transaction code, the version of the NCPDP standard, the ID of the service provider, the service date, and other fields.

A header does not use separators; it consists of fixed lengths fields.

Here is the transaction header from our example:

␂G11234567890123456D1B101        1234567890123     202108210000000100	

Note the B1 substring – this is our transaction code (claim billing). We now know what segments will follow the header – they are defined by the standard for B1 transactions.

Here is our header in JSON format:

{
  "transaction_header": {
    "transaction_reference_number": "1234567890",
    "bin_number": 123456,
    "version_release_number": "D1",
    "transaction_code": "B1",
    "process_or_control_number": "01",
    "transaction_count": "1",
    "service_provider_id_qualifier": "23",
    "service_provider_id": "4567890123",
    "date_of_service": "2021-08-21",
    "software_vendor_certification_id": "0000000100"
  }
}

The NCPDP batch standard introduces a batch header and a batch trailer (in addition to the transaction header defined by the telecom standard). They communicate supplemental information about the batch, such as a batch creation date.

The batch standard also introduces ␂ (STX) and ␃ (ETX) separators to make it easier to identify the start/end of headers and transactions within a batch.

The batch standard adds a few extra fields to the transaction header. The batch standard also stipulates that the ␂ (STX) character must precede each header. The telecom standard does not use ␂ (STX) or ␃ (ETX); it simply assumes that the header is the first line of the request (recall that the telecom standard is geared towards a request-response model with a single transaction in the request).

This post provides additional information about transaction headers.

Data Types

NCPDP supports all the usual data types for fields: string, date, integer, and decimal numbers.

Numeric fields can be left-padded with zeros. Decimal numbers do not contain the decimal point, meaning we have to consult the standard to determine their precision.

NCPDP uses the so-called signed overpunch to encode the sign of the number using the last digit. The signed overpunch was widely used on mainframes; the NCPDP standard relies on it to this day.

The idea of signed overpunch is to convert a number’s last digit into a letter based on its alphabetical order. E.g., A is 1, B is 2, and so on. { is mapped to zero. If the number is negative, we start with “J”; that is, J is 1, K is 2, and so on. As a result, we saved the byte that otherwise would’ve been used for the sign.

Examples:

Field Input Value Number
Days Supply 030 30
Quantity Dispensed 0000030000 30.00
Gross Amount Due 0000084F 8.46
Negative Dollar Amount 0000084J -8.41
Zero Dollar Amount 0000000000{ 0.00

Repeating Fields

NCPDP supports repeating fields or groups of fields. We will address repeating fields in a future post.

Complete Example

Here’s our complete example in JSON format. You can use our free online NCPDP viewer to convert your own NCPDP text into JSON or to browse NCPDP in a human-readable form.

{
  "transactions" : [ {
    "transaction_header" : {
      "transaction_reference_number" : "1234567890",
      "bin_number" : 123456,
      "version_release_number" : "D1",
      "transaction_code" : "B1",
      "process_or_control_number" : "01",
      "transaction_count" : "1",
      "service_provider_id_qualifier" : "23",
      "service_provider_id" : "4567890123",
      "date_of_service" : "2021-08-21",
      "software_vendor_certification_id" : "0000000100"
    },
    "insurance" : {
      "cardholder_id" : "123456789",
      "cardholder_first_name" : "JANE",
      "cardholder_last_name" : "DOE",
      "plan_id" : "MYPLAN",
      "eligibility_clarification_code" : "0",
      "group_id" : "GR1",
      "person_code" : "001",
      "patient_relationship_code" : "2"
    },
    "patient" : {
      "date_of_birth" : "1980-02-25",
      "patient_gender_code" : "Female",
      "patient_first_name" : "JANE",
      "patient_last_name" : "DOE",
      "patient_street_address" : "100 MAIN STR",
      "patient_city_address" : "WASHINGTON",
      "patient_state_province_address" : "DC",
      "patient_zip_postal_zone" : "100010000",
      "patient_phone_number" : "5551234567"
    },
    "claim" : {
      "prescription_service_reference_number_qualifier" : "1",
      "prescription_service_reference_number" : "000000123456",
      "product_service_id_qualifier" : "Drug Info - NDC",
      "product_service_id" : "00003089421",
      "quantity_dispensed" : 3E+1,
      "fill_number" : "01",
      "days_supply" : 30,
      "dispense_as_written" : "0",
      "date_prescription_written" : "2021-07-01",
      "prescription_origin_code" : "3",
      "other_coverage_code" : "00",
      "special_packaging_indicator" : "3",
      "unit_of_measure" : "EA"
    },
    "pricing" : {
      "ingredient_cost_submitted" : 5.71,
      "dispensing_fee_submitted" : 2.75,
      "patient_paid_amount_submitted" : 1.62,
      "usual_and_customary_charge" : 0,
      "gross_amount_due" : 8.46,
      "basis_of_cost_determination" : "07"
    },
    "prescriber" : {
      "prescriber_id_qualifier" : "01",
      "prescriber_id" : "1234567890",
      "prescriber_last_name" : "EVIL",
      "prescriber_phone_number" : "5557654321"
    }
  } ]
}

Please use our viewer to decipher your NCPDP files. You can also use our API to programmatically convert your NCPDP transactions into JSON.