Rates + Requirements
Rates and coverage rules in the same row. No other published dataset has both.
Rates and the rules that gate them in the same row, so you can rank insurers by how hard they are to work with — not just by price.
Buy the slice you need
You do not have to take the whole grid. Every slice is the same columns, the same quality gates and the same quarterly refresh over less of it — and slices stack, so nothing is ever bought twice.
One drug, joined
One drug’s rates and coverage rules across the 30 insurers where we hold both.
What is in it
- Every column from the rate data, plus the rules that gate that drug for that insurer
- A 0 to 100 friction score combining prior authorization, step therapy, site limits and renewal frequency
- A single flag marking where an insurer pays below the federal benchmark and makes the drug hard to get
- The policy version and dates behind every joined row, so any finding traces back to a quoted sentence
Questions it answers
- Rank every insurer by what they pay for our drug and how hard they make it to get.
- Where is our drug both underpaid and sitting behind a competitor in step therapy?
- Which markets should the access team work first, and why?
What it does not do
An insurer needs loaded rates and parsed policy to appear at all. Check coverage before assuming yours is in it.
It tells you what was contracted and what was required, not what was paid on any individual claim.
Who buys this
- Market access teams launching or defending a product
- Manufacturers facing biosimilar competition
- Teams currently answering this by comparing two spreadsheets by hand
Why it is worth the money
One question, one query
Which insurers pay below ASP+6% and also require two drugs to fail first? That needs rates and rules in the same row. No other published dataset carries both.
A friction score you can sort on
Prior authorization, step therapy, site limits and renewal frequency combine into a single 0 to 100 number per insurer and drug, so you can rank a market in one pass.
A flag for the worst combination
One column marks where an insurer pays below the federal benchmark and makes the drug hard to get. That combination is usually what the analysis was looking for.
Every finding traces back
Each row carries the policy identifier and its dates, so any number walks back to a quoted sentence and a link to the insurer’s document.
What a row looks like
Real rows from the current build, in the shape this dataset ships.
| Insurer | State | Rates | p10 | Median | p90 | Quality | Flagged |
|---|---|---|---|---|---|---|---|
| uhc | NY | 6,221 | $23.36 | $33.23 | $54.72 | 72.5 | no |
| uhc | CA | 6,092 | $25.52 | $34.83 | $64.87 | 72.5 | no |
| uhc | FL | 5,923 | $24.03 | $32.99 | $58.86 | 72.5 | no |
| aetna | FL | 5,611 | $30.03 | $1,591.69 | $4,227.98 | 65.0 | yes |
| uhc | TX | 5,472 | $24.41 | $33.22 | $57.82 | 72.5 | no |
| aetna | CA | 5,329 | $31.64 | $1,654.20 | $4,295.29 | 65.0 | yes |
The columns
Published in full, before you talk to anyone. Whether this fits your model is a technical question and you should be able to answer it yourself.
rate_intel
Specialty and infusion rates at tax-ID level, with the ghost count, the confidence interval and the federal benchmark already on every row. This is the production table, column for column.
Key vintage × payer × state × billing_code × billing_code_modifier × billing_class × tin
| Column | Type | What it is |
|---|---|---|
vintage key |
TEXT | Which quarterly build the row belongs to. Current is 2026-Q2-06. |
payer key |
TEXT | The insurer the rate is attributed to. |
src_payer |
TEXT | The file it came out of. Kept because one insurer’s file can carry rates for several. |
state key |
TEXT | Two-letter state. |
billing_code key |
TEXT | HCPCS or CPT. |
billing_code_modifier key |
TEXT | Part of the key. Averaging across modifiers gives a wrong number that looks right. |
service_code |
TEXT | Place-of-service grouping as the insurer filed it. |
billing_class key |
TEXT | professional or institutional. |
negotiated_type |
TEXT | negotiated, fee schedule, derived, or blank. |
tin key |
TEXT | Tax ID. This is what makes the table entity-level rather than market-level. |
n_obs |
BIGINT | Observations behind the row after filtering. |
n_raw |
BIGINT | Observations before filtering. |
n_ghost |
BIGINT | How many were ghost rates — codes that provider would never bill. Counted, not silently dropped. |
n_unit_uncertain |
BIGINT | Rows whose billing unit could not be resolved. Per-vial against per-milligram lives here. |
rate_raw |
DOUBLE | Before unit normalization. |
rate_final |
DOUBLE | After. This is the number to use. |
sd_used |
DOUBLE | Standard deviation behind the interval. |
ci_low |
DOUBLE | Lower bound of the confidence interval. |
ci_high |
DOUBLE | Upper bound. A wide interval is telling you something. |
veracity |
TEXT | measured where the rate is observed, otherwise how it was derived. |
proxy_source |
TEXT | What stood in when the rate was not directly observed. |
confidence |
DOUBLE | 0 to 1. Set your own floor; ours is high. |
medicare_bench |
DOUBLE | Medicare allowed for the same code and locality. |
asp_per_unit |
DOUBLE | CMS average sales price. Drugs only, null for procedures. |
asp_plus6 |
DOUBLE | ASP plus 6 percent, the federal drug benchmark. |
ratio_vs_medicare |
DOUBLE | The rate over the Medicare allowed amount. |
ratio_vs_asp6 |
DOUBLE | The rate over ASP+6%. Under 1 means commercial pays less than the federal benchmark. |
anchor_source |
TEXT | What the row was anchored against, usually medicare. |
triangulation |
TEXT | Whether independent sources agreed. |
coverage_cell
One row per drug and insurer: whether prior authorization applies, what has to be tried first, which diagnoses are covered, and where the drug may be given.
Key payer_slug × drug × lob
| Column | Type | What it is |
|---|---|---|
payer_slug key |
TEXT | The insurer. Joins to the rate tables. |
drug key |
TEXT | Active ingredient. Coverage rules are written at this level, not at code level. |
lob key |
TEXT | Line of business, taken from the policy and never inferred. Every row in the current build is commercial; Medicare Advantage, Medicaid and exchange are the same column and are not yet populated. |
prior_auth_required |
BOOLEAN | Whether approval is needed before the drug is given. True on 81% of rows. |
preferred_products |
TEXT[] | What the insurer wants tried first. |
products |
JSONB | Product-level detail where the policy distinguishes brands or biosimilars. |
covered_dx |
JSONB | Covered diagnoses with their ICD-10 codes and any dose ceiling, keyed by indication. |
site_of_care |
JSONB | Whether a site-of-care program applies and what it says. |
citations |
JSONB | The quote behind each field, so any value can be traced to a sentence. |
source_url |
TEXT | Direct link to the insurer’s own document. |
effective_date |
DATE | The insurer’s policy date. Present on 85% of rows. |
veracity |
TEXT | How the row was established: verified on 1,625 rows, corroborated on 798. |
confidence |
TEXT | Confidence in the extraction, high or medium. Nothing lower is shipped. |
signals |
JSONB | Supporting evidence found while reading the policy. |
attested_absent |
TEXT[] | Requirements we looked for in the policy and confirmed are not there — a step-therapy rule, a TB screen, a site-of-care program. A verified absence, not a gap. Non-empty on 1,577 of 2,423 rows. |
coverage_rule
The individual rules behind each cell, each carrying the sentence it came from.
Key rule_id — one row per rule
| Column | Type | What it is |
|---|---|---|
rule_id key |
TEXT | Primary key. One row per rule. A single drug-and-insurer pair routinely carries many rules of the same type — one policy states twenty separate clinical prerequisites — so the other columns do not form a key and joining on them fans rows out. |
payer_slug |
TEXT | The insurer. Joins to coverage_cell and to the rate tables. |
drug |
TEXT | Active ingredient. |
rule_type |
TEXT | covered_indication, step_therapy, site_of_care, quantity_limit, reauth, exclusion and so on. |
indication |
TEXT | What the rule is about, e.g. rheumatoid_arthritis. Empty where the rule applies to the drug generally rather than to one diagnosis. |
hcpcs |
TEXT | The billing code the rule attaches to, and the join to the rate tables. Present on 43% of rules: the rest are written about the drug rather than about a code, and we do not attach a code the policy did not name. At the cell level 76% carry at least one coded rule. |
value |
JSONB | The parsed rule — ICD-10 list, dose ceilings, required prior drugs, notes. |
citation_quote |
TEXT | The exact sentence from the policy. Never reworded. |
source_url |
TEXT | Link to the document the quote came from. |
effective_date |
DATE | When the policy version took effect. |
Traps in this data, and how we handle them
These catch people out whoever they buy from. They are worth knowing before you model anything with rate or coverage data, including ours.
Both halves have to exist for a row to exist
Why it bitesThe join is only as broad as the overlap between loaded rates and parsed policy. An insurer missing either one does not appear at all, and a thin overlap can look like a finding when it is really a coverage gap.
How we handle itThe overlap is published on the coverage page, and every row carries the counts behind it so a thin cell is visible rather than misleading.
Rules are written about ingredients, prices are recorded against codes
Why it bitesA coverage policy usually names the molecule. A rate is filed against a billing code. The two do not map one to one, especially where biosimilars share a reference product.
How we handle itWhere a rule governs the molecule rather than a specific code we join at molecule level and mark the row, so you know which kind of match you are looking at.
A friction score is a summary, not a verdict
Why it bitesCombining prior authorization, step count, site limits and renewal frequency into one number makes markets comparable. It also hides which component is driving the score.
How we handle itThe score ships next to its components, never instead of them, and every row links back to the verbatim rules it was built from.
Everything the rate datasets get wrong, this inherits
Why it bitesGhost rates, percentage-of-charge rows, network blending and modifier collapsing all apply here too, because the rate half of the join is the same data.
How we handle itSame handling: provider counts, quality scores, rate type carried with the value, and networks kept distinct.
What to know before you buy
- The dataset covers where the two halves overlap. An insurer needs both loaded rates and parsed policy to appear, and the overlap is published on the coverage page.
- Rules are written about ingredients more often than codes. Where that happens we join at ingredient level and mark the row.
This dataset is still in preview
Tell us what you need from it and we will tell you honestly where it is and when it lands.