for Pharma
Toggle menu
Answers · Pharma data quality

Why don't our specialty pharmacy, 867, and sales numbers match?

They rarely match because each feed counts a different thing: different date definitions, different weeks, units versus packages, and NDCs at different levels. Normalize those four before you reconcile, then test each feed against its own history, because a partial file or a restatement looks exactly like a real gap.

Chris Bergh Published

Key points

  • Specialty pharmacies disagree on what ship date, fill date, and dispense date mean, and on when a referral counts, so two pharmacies can report the same patient in different weeks.
  • Three vendors can carry three different definitions of a week, all reasonable and none the same, so weekly totals disagree before any data is wrong.
  • An EDI 867 quantity that switches from units to packages makes one product show a 10x jump that the dashboard renders as a strong sales week.
  • 867 files and claims carry NDCs at package level in 11-digit form while product masters carry the two-segment product form, and a bare 10-digit NDC can belong to three different products.
  • A specialty pharmacy file that should carry 40,000 rows and arrives with 26,000 loads with no error, so test volume against that feed's own history before reconciling across feeds.

Three feeds describe the same drug moving to the same patients, and they never agree. Your distributor’s EDI 867 says one number. The specialty pharmacy network says another. The syndicated sales feed says a third. The brand team wants to know which one is right by Wednesday.

Usually all three are right about different things. The work is making them describe the same thing before you compare them.

Four normalizations before any reconciliation

Pick one event date

No two specialty pharmacies agree on what ship date, fill date, or dispense date means. One counts a referral the day it arrives, the next the day benefits clear, the third when the first box goes out the door. The same patient can land in different weeks depending on which pharmacy filled them.

Pick one calendar

The time and calendar dimension is where three vendors carry three definitions of a week, all reasonable, none the same. Map every feed to your fiscal week before comparing weekly totals.

Pick one unit

An 867 quantity column can arrive as units one month and packages the next, or a price can land in cents. One product shows a 10x jump. Nobody flagged the unit-of-measure change.

Pick one NDC level

Your 867 files and claims carry package-level NDCs in 11-digit form. Your product master carries the two-segment product form. And a 10-digit NDC with its hyphens stripped is ambiguous, as this illustrative value shows:

FDA layoutSegmentedPadded to 11 digits
4-4-21234-5678-9001234567890
5-3-212345-678-9012345067890
5-4-112345-6789-012345678900

An illustrative value, not a real product. The same ten characters pad to three different 11-digit codes, and nothing in the value says which layout you’re holding.

That is why TestGen’s Valid NDC rejects a bare 10-digit string by default. Treating it as valid is how the wrong product ends up in a report. It is also why the NDC tests default to Warning: a format mismatch between a hyphenated vendor feed and an unhyphenated master is usually a convention difference, not a broken value.

Then test each feed against itself

Reconciling across feeds assumes every feed arrived whole. Check that first.

SymptomLikely causeWhat to run
Specialty pharmacy dispenses short this weekPartial file: 26,000 rows against a normal 40,000, load greenVolume bounds learned from that feed’s history
Patient count higher than dispenses suggestSame patient under three de-identified tokensNone reliably: you cannot tell the tokens apart, so treat the count as an upper bound
Four records for one patient on one dayEnd-of-day status snapshotDuplicate Rows on patient and day, after keeping the last status
Metric empty after a vendor changeColumn renamed from RX_CNT to RxCount, nulls filledSchema drift
One product 10xUnits became packagesMetric Trend against history
Group totals swap between basketsNDC remapped to a different market basketAggregate Balance
Last quarter moved in the sales feedVendor restatementSnapshot diff against the prior delivery

Every row loads without an error. That is the whole problem.

The partial file and the renamed column come from the commercial data most likely to be wrong. The four-records-per-patient pattern comes from a small pharma whose specialty pharmacy sends four files a day, patient status, dispense, inventory, and demographics, and whose status file is an end-of-day snapshot: a patient who moves through every stage in one day arrives as four records. The market basket remap is the Aggregate Balance example from our testing post. Restatement in the syndicated feed gets its own treatment in the feed-by-feed reference.

What’s left is the real gap

Once the event date, the week, the unit, and the NDC level line up, and each feed has passed against its own history, the remaining difference between 867 and dispense is something worth explaining to the brand team. Before that, you are reconciling definitions.

Two more residuals show up after normalization. Copay redemptions that never reconcile to a dispense usually trace to a plan or bridge-file mapping change. And a chain that stops reporting stocking data reads as lost stocking rather than missing data. Both look like market movement until a test says otherwise.

Specialty pharmacy integration is almost always somebody’s afterthought, right up until it becomes the number the access team is betting the launch on.

Follow-up questions

Frequently asked questions

Why does the specialty pharmacy report a different week than the distributor?

Because the feeds define both the event and the week differently. One pharmacy's ship date is another's fill date and a third's dispense date, and three vendors can carry three definitions of a week. Map every feed to one event date and one fiscal calendar before you compare weekly totals, or the difference you investigate is a calendar artifact.

Why did one product jump 10x in our 867 data?

Usually a unit-of-measure change. A quantity column arrives as units one month and packages the next, or a price lands in cents instead of dollars, and one product shows a 10x jump. Nothing errors, because every value is valid. A volume or metric trend test against that product's own history catches it on the load where it first appears.

Can the same NDC look different in two feeds?

Yes. 867 files and claims carry package-level NDCs in 11-digit form, while product masters and formulary files carry the two-segment product form. Strip the hyphens from a 10-digit NDC and an illustrative value such as 1234567890 could be 4-4-2, 5-3-2, or 5-4-1, which pad to three different 11-digit codes. TestGen's Valid NDC rejects the bare 10-digit form for that reason.

Why do patient counts from specialty pharmacy run high?

Because each specialty pharmacy de-identifies patients its own way, so the same patient can appear three times under three tokens. Status files add a second effect: an end-of-day snapshot means a patient who moves through every stage in one day arrives as four records. Settle the status logic before you count, and treat a cross-pharmacy patient count as an upper bound.

Should we reconcile the feeds against each other first?

No. Test each feed against its own history first. A partial specialty pharmacy file, 26,000 rows against a normal 40,000, loads with no error and makes every cross-feed comparison wrong. Volume bounds learned from history, freshness checks, and schema drift tests stop the bad file in staging, so the cross-feed difference you investigate is a real one.

Talk to the team that tests this data every week.

Half an hour on your stack, your launch window, and what the first sprint would look like.