Medicare Allowed Amount API: Build From CMS Files or Buy

Building a Medicare allowed amount API from CMS's RVU, GPCI and ZIP files: the formula, the real work, what breaks in production and when to use an API instead.

Updated CMS RVU26D12 min read

Soft clay still life of three upright file folders beside a small sorting tray holding a forest-green gear, with a neat stack of blank index cards on the right, on a warm off-white background.
On this page 8 sections
  1. What CMS publishes
  2. The formula is the easy part
  3. What a DIY build actually involves
  4. What breaks in production
  5. Can I use a CMS API instead?
  6. Or call an API built on the same files
  7. When to build it, and when to buy it
  8. FAQ

CMS doesn't publish an API that returns a Medicare allowed amount for a code and a ZIP. To get one, you either build it yourself from CMS's quarterly RVU, GPCI, conversion factor and ZIP-to-locality files, or you call a Medicare allowed amount API built on those same files, such as FeeBase (plans from $49/month). The formula fits on one line; the work is in the files: release dates, split ZIP codes, two conversion factors, status codes and corrected re-issues.

Key takeaways

  • The Physician Fee Schedule amount is (work RVU × work GPCI + PE RVU × PE GPCI + MP RVU × MP GPCI) × conversion factor. Every input is in a public CMS file.
  • CMS's PFS data catalog at pfs.data.cms.gov has a free, open query API, but it returns RVU and GPCI rows, not prices, and has no ZIP crosswalk.
  • The CMS "Procedure Price Lookup" API is not a physician fee schedule API: it needs an AMA license and a CMS-issued key, and returns national hospital outpatient and ASC averages.
  • A correct build has to pick the release by date of service, resolve split ZIPs with ZIP+4, choose QP or non-QP, and refuse to price codes Medicare doesn't price on the fee schedule.
  • Parsing the files once is the easy part. The cost is keeping the answer right every quarter after that.

What CMS publishes

Everything a Medicare fee schedule API needs is public, but it's spread across separate CMS downloads with different schedules and layouts.

File What's in it How often The catch
PFS relative value files (RVU26A–D) RVU file (PPRRVU) with RVUs, status codes and payment indicators; GPCI file; anesthesia CF; OPPS cap; locality key Quarterly, re-issued when CMS corrects a file From 2026, two RVU payment files per release (QP and non-QP). File names change between quarters and years.
ZIP code to carrier locality file (ZIP5) Every five-digit ZIP mapped to a MAC and payment locality Quarterly Some ZIPs span more than one locality and are flagged as needing ZIP+4.
ZIP+4 file (ZIP9) Locality by ZIP+4 range for the split ZIPs Quarterly Over a million rows; you need it for the minority of ZIPs that are split.
Clinical Laboratory Fee Schedule Payment amounts for lab codes Quarterly Lab codes with PFS status X aren't priced from the RVU file at all.
Anesthesia base units Base units per anesthesia code Separate CMS file Anesthesia is base units plus time units, not RVUs.

The ZIP files are listed on CMS's fee schedules general information page. Here's the scale of CMS's October 2026 files:

109payment localities in the RVU26D GPCI file
42,957five-digit ZIP rows, Q4 2026
580of those ZIPs flagged as needing ZIP+4
1,087,640ZIP+4 rows, Q4 2026

The formula is the easy part

A Physician Fee Schedule amount is three relative value units (work, practice expense, malpractice), each multiplied by the geographic practice cost index (GPCI) for the payment locality, summed, then multiplied by the conversion factor. Use the facility or non-facility practice expense RVU depending on where the service was furnished. In 2026 there are two conversion factors: 33.4009 for non-QP clinicians and 33.5675 for QPs. The RVU guide walks through each part.

How the rate is built · 99214

RVUs × geographic indexes × conversion factor

Office or facility?

Work1.92

1.92 RVUs× 1.000 GPCI

Practice expense2.00

2.00 RVUs× 1.000 GPCI

Malpractice0.14

0.14 RVUs× 1.000 GPCI

Adjusted RVUs

4.0600

Conversion factor

$33.4009

Medicare rate

$135.61

Every GPCI starts at 1.000, the national rate. Enter a ZIP or drag a slider.

If you only ever needed one code at national GPCIs on today's file, you'd be done. A product that prices claims for real practices needs much more.

What a DIY build actually involves

This is the work behind "just load the CMS files into Postgres", in the order you'll meet it:

  1. Download and keep every release. CMS publishes RVU files quarterly (RVU26A, B, C, D) and re-issues an archive when it corrects one, with a new "updated" date in the URL. Keep each archive and its checksum; you'll need the old ones to price earlier dates of service and to show where a number came from.
  2. Parse files whose names and layouts drift. Real file names from CMS archives include PPRRVU25_JAN.csv, PPRRVU2025_Jul.csv and, from 2026, PPRRVU2026_Oct_nonQPP.csv beside PPRRVU2026_Oct_QPP.csv. GPCI files have been named "CY 2014 GPCI _12172013.csv", "CY2015_GPCIs.csv" and "GPCI2026.csv". Header rows and column positions need checking on every import.
  3. Load both 2026 payment files. The QP and non-QP files share RVUs but carry different conversion factors. Decide how a caller tells you which one applies, and default to non-QP. See QP vs non-QP.
  4. Join GPCIs by MAC and locality. The GPCI key is the contractor number plus the locality number, not the state.
  5. Map ZIP to locality from the same quarter's crosswalk. Use ZIP5 for most ZIPs and the ZIP+4 file for the ones CMS flags as split.
  6. Pick the release by date of service. A claim from March needs the January release, not the file you downloaded this morning. Within a quarter, the latest corrected archive replaces the earlier one.
  7. Respect status codes. Statuses A, R and T are priced from RVUs. C is priced by the MAC, not the fee schedule. X codes go to the Clinical Laboratory Fee Schedule. J (anesthesia) is base units plus 15-minute time units times the locality's anesthesia conversion factor. Other statuses aren't paid on the fee schedule.
  8. Handle the setting. Choose the facility or non-facility PE RVU from the place of service, and treat an NA indicator as "no amount in this setting", not as zero. See facility vs non-facility.
  9. Price modifiers 26 and TC from their own rows. Professional and technical components have separate rows in the RVU file; they aren't a percentage of the global amount.
  10. Apply provider rules if you need them. NPs, PAs and CNSs are paid 85% of the fee schedule; LCSWs, LMFTs and LPCs 75%; non-participating providers 95%, with a limiting charge of 115% of that. Therapy services add the multiple procedure payment reduction.
  11. Flag OPPS-capped rows. Each RVU archive includes CMS's OPPS cap file, which lists services whose fee schedule payment is capped at the hospital outpatient (OPPS) amount. Either implement the cap or mark those results.
  12. Use decimal arithmetic. Multiply RVUs, GPCIs and the conversion factor as decimals and round to cents once, at the end. Binary floating point can land a cent away from CMS's amount.

What breaks in production

Most DIY fee schedule APIs work in the demo and fail on real claims. These are the failures to test for:

Mistake What the user sees
Pricing every request from the current file Claims from an earlier quarter come back at the wrong rate after each update
Picking one locality for a split ZIP A practice on one side of the boundary gets its neighbor's GPCIs
Returning 0 for contractor-priced (C) codes A code that Medicare pays shows as worth nothing
Pricing lab (X) codes from the RVU file Lab codes come back empty or wrong instead of at the CLFS amount
Applying one conversion factor to everyone Every amount for a QP clinician is slightly low, or every non-QP amount slightly high
Missing a re-issued archive The corrected rows CMS published never reach your API
Treating an NA practice expense as zero A facility-only service shows an office rate built without practice expense
Floating-point maths Totals are a cent off CMS's own amounts

The recurring work is the expensive part. Every quarter: download the new RVU and ZIP archives, check the file names and columns, load them as a new effective-dated release, rerun your reference prices against CMS's tools, and watch for re-issued archives. Every January: add the new year's conversion factors and file layouts, and whatever new payment rule the final rule introduced (2026's was the QP split).

Can I use a CMS API instead?

CMS has two things that look like an answer. Neither returns a price for a code at a ZIP.

The Procedure Price Lookup (PPL) API at developer.cms.gov/ppl-api. CMS says that "to use the PPL API, you must have an AMA license and an API key"; CMS reviews key requests, and keys expire every 60 days. It covers about 3,900 procedures with national average payments for ambulatory surgical centers and hospital outpatient departments. It doesn't cover the Physician Fee Schedule, localities or ZIPs. None of the APIs listed on developer.cms.gov is a physician fee schedule pricing API.

The PFS data catalog at pfs.data.cms.gov. This is a public data catalog with an open, keyless JSON query API over the same tables CMS's PFS Look-Up Tool displays. Each year has an Indicators dataset (RVUs, payment indicators, conversion factor) and a Localities dataset (GPCIs). It returns table rows, so you still apply the formula, choose the PE RVU, pick the conversion factor and map the ZIP yourself; there's no ZIP crosswalk dataset. In 2026 each code appears twice, once per conversion factor, with no column naming which is QP. And the catalog keeps one Indicators dataset per year and updates it in place, so it answers "what is the rate now", not "what was it on the date of service".

Both are good at what they're built for. The CMS PFS Look-Up Tool guide covers the manual tool in detail.

Or call an API built on the same files

FeeBase loads the same CMS archives (RVU, GPCI, conversion factor, ZIP5 and ZIP+4, CLFS) as effective-dated releases (Physician Fee Schedule and ZIP crosswalk releases back to January 2013), and computes the same formula with decimal precision. Its amount isn't an estimate of the CMS number; it is the CMS number, computed from CMS's rows. You don't have to take that on trust: add include=sources and each amount comes back with the CMS archive, file and line it was built from.

A request for a code at a ZIP on a date of service:

curl -G https://feebase.co/api/v1/rates/99214 \
  -H "Authorization: Bearer $FEEBASE_API_KEY" \
  -d setting=non_facility \
  -d zip=10001 \
  -d date=2026-10-15 \
  -d include=sources

The response, trimmed. Amounts are integer cents:

{
    "code": "99214",
    "amount": "<integer cents>",
    "currency": "usd",
    "setting": "non_facility",
    "date": "2026-10-15",
    "qp_status": "non_qp",
    "location": { "type": "locality", "id": "13202-01" },
    "payment_status": "A",
    "fee_schedule": "pfs",
    "sources": [
        {
            "kind": "rvu",
            "release": { "label": "RVU26D" },
            "file": "PPRRVU2026_Oct_nonQPP.csv",
            "line": 13016
        },
        {
            "kind": "gpci",
            "release": { "label": "RVU26D" },
            "file": "GPCI2026.csv",
            "line": 78
        },
        {
            "kind": "geography",
            "release": { "label": "ZIP2026Q4" },
            "file": "ZIP5_OCT2026.txt",
            "line": 26150
        }
    ]
}

The same lookup in Python:

import os
import requests

key = os.environ["FEEBASE_API_KEY"]
response = requests.get(
    "https://feebase.co/api/v1/rates/99214",
    headers={"Authorization": f"Bearer {key}"},
    params={
        "setting": "non_facility",
        "zip": "10001",
        "date": "2026-10-15",
    },
    timeout=10,
)

if response.status_code == 422:
    # e.g. zip_plus4_required: send ZIP+4 or a locality ID
    print(response.json()["error"]["code"])
else:
    response.raise_for_status()
    rate = response.json()
    if rate["amount"] is None:
        print("Not priced:", rate["unavailable_reason"])
    else:
        print(rate["code"], rate["amount"] / 100, "USD")

The awkward cases from the list above are handled the same way every time:

  • Date of service picks the CMS release in effect, and the latest corrected archive within it.
  • Split ZIPs return 422 zip_plus4_required instead of a guess; ZIP+4 or a locality ID resolves them (locations).
  • QP status is a parameter (qp_status=qp or non_qp, default non-QP).
  • Contractor-priced and non-payable codes return amount: null with a machine-readable unavailable_reason, never a zero. OPPS-capped rows are flagged the same way; the cap itself isn't calculated.
  • Lab codes are priced from the Clinical Laboratory Fee Schedule; anesthesia codes take anesthesia_minutes.
  • Modifiers 26 and TC, provider type and non-participating pricing with the limiting charge are parameters on the same endpoint (rates reference).

The methodology page traces a full calculation to its source rows and lists the SHA-256 checksum of every CMS archive loaded. Coverage lists the releases available.

When to build it, and when to buy it

Build it yourself when the job is small and fixed: a one-off analysis, a research dataset, or a single national number. CMS's own tools and catalog are free and authoritative, and the free FeeBase lookup prices a code list at a ZIP and date of service without writing any code.

Build it yourself, too, if you want to own the pipeline and can staff the quarterly work in the section above for as long as the product exists. That's a reasonable choice; just budget for the maintenance, not the first parse.

Use an API when the number is a product feature: a practice management system, a claims or contract tool, a patient estimate, anything that has to be right for every ZIP, date of service and quarter. FeeBase's API plans start at $49/month, with keys, versioned /v1 endpoints and documentation. FeeBase is independent and isn't affiliated with or endorsed by CMS.

Sources: CMS, PFS relative value files (RVU26D, rvu26d-updated-08-26-2026.zip); CMS, fee schedules general information and ZIP code to carrier locality file (October 2026); CMS, CLFS 2026 Q4; CMS, Procedure Price Lookup API and developer.cms.gov; CMS, PFS data catalog and its query API; CY 2026 PFS final rule (CMS-1832-F) for the conversion factors. Counts are from CMS's files effective October 1, 2026, as imported by FeeBase: 109 localities from the RVU26D GPCI file; 42,957 ZIP rows, 580 of them flagged as needing ZIP+4, and 1,087,640 ZIP+4 rows from the ZIP code to carrier locality file updated August 13, 2026. Verified October 10, 2026.

FAQ

Does CMS have an API for the Physician Fee Schedule?

Partly. The PFS data catalog at pfs.data.cms.gov has a free, open JSON query API that returns RVU, indicator and GPCI rows for each year. It doesn't calculate a price, map ZIP codes to localities or keep earlier quarters of the current year. CMS's Procedure Price Lookup API is a different product: AMA license and key required, national ASC and hospital outpatient averages only.

Is there a REST API that returns the Medicare allowed amount for a CPT code and ZIP code?

Not from CMS. FeeBase's API does: GET /api/v1/rates/{code} with a ZIP (or ZIP+4), setting and date of service returns the Physician Fee Schedule amount in integer cents, with the CMS file and line behind it when you add include=sources.

Is there a free Medicare fee schedule API?

CMS's pfs.data.cms.gov query API is free and returns the raw rows. FeeBase's API is paid, with plans from $49/month. FeeBase's free web lookup prices codes at a ZIP and date in the browser, but it isn't an API.

How do I get the Medicare allowed amount for a CPT code in Python?

Either download CMS's RVU, GPCI and ZIP crosswalk files and apply the formula yourself, or call a pricing API with requests, as in the example above. If you build it, use decimal.Decimal rather than floats and pick the release by date of service.

Can I load the CMS fee schedule files into my own database?

Yes. They're public CMS files. Plan for two RVU payment files per release from 2026, the ZIP+4 file for split ZIPs, effective-dated releases, re-issued archives and changing file layouts, every quarter.

Should I check an API's amount against CMS?

You can, and it should match: same code, locality, setting, modifier and conversion factor in, same amount out. With FeeBase, include=sources gives you the exact CMS rows to compare against.

Did this answer your question about Medicare Allowed Amount API: Build From CMS Files or Buy?

Tell us what you were actually trying to work out. We’ll answer you directly, or build the page that does.