Skip to main content
Plan Benefits is one of haau3’s two Benefits services, the two halves of CMS’s Real-Time Benefits use case. Plan Benefits answers what a Medicare Advantage or Marketplace plan covers and what a member pays, from CMS’s plan files; Pharmacy Benefits answers what a medication would cost, in real time. Look up a Medicare Advantage or ACA Marketplace plan and get what it covers and what a member pays: its deductibles and out-of-pocket maximums, and the cost of core services such as a primary care visit, an emergency room visit or a hospital stay, in network and out of network. Each plan is a FHIR InsurancePlan, read from the files the Centers for Medicare & Medicaid Services (CMS) publishes, and each names the CMS release it was read from. This is plan design, the same for every member of a plan. Nothing about a member is sent here.

Service base

Everything hangs off that base, exactly as the FHIR REST specification describes. /v1/ is the version of the haau3 platform API contract, not a FHIR version. The FHIR release is r4, and every response says so:
You never have to ask for a release. A plain Accept: application/fhir+json, or no Accept header at all, works fine. If you do ask for one we do not serve, or for a format other than JSON (in Accept or _format), you get a 406 rather than a silent substitution. Every error on this base is a FHIR OperationOutcome, including the 401 you get without a key and a 429, so a FHIR client only ever has one error shape to parse. Errors, limits and request ids lists the statuses every service shares.
The uppercase form /v1/fhir/R4/... redirects to the lowercase base with a 308, which preserves the method and body so a POST is not quietly turned into a GET.
The Terminology service, the Provider directory, Questionnaires, MedList and Pharmacy Benefits use this same base and the same CapabilityStatement.

What is served

GET [base]/metadata returns the CapabilityStatement. Its InsurancePlan entry names the release each program is serving, and anything missing from it is refused by name. Two programs are served:
  • Medicare Advantage, from CMS’s Plan Benefit Package (PBP) Benefits files for plan year 2027.
  • ACA Marketplace, from CMS’s Marketplace public use files for plan year 2026: the plans sold through HealthCare.gov.

Plans to try

Read a plan

A plan’s id is the id people know it by:
  • Medicare Advantage: CMS’s plan id, contract, plan and segment, with the segment written in three digits: H2406-013-000.
  • ACA Marketplace: the 17-character HIOS plan id, the 14-character standard component and a two-digit variant: 19898FL0340001-01. Each cost-sharing reduction variant of a plan is a plan of its own.
A plan the releases being served do not hold answers 404. So does a drug-only or dental-only plan, which is held but is not a medical plan, and the OperationOutcome says so. Find the plans sold in a state whose name contains some words:
Find the plans a person can buy on their own in one county, Miami-Dade County, Florida, whose county code is 12086:
Find a plan by an id you already hold, in either form:
A search needs identifier, a form of name, coverage-area-state or coverage-area-county. type and sold-to narrow a search but are not one, so a search for every Marketplace plan is refused. Every other parameter is refused by name rather than ignored, so a search never quietly answers a different question than the one asked. A drug-only or dental-only plan is never in a name, state or county search; an identifier search that finds one answers no plan and an OperationOutcome entry saying why.

Where a plan is sold

CMS’s files say where a plan is sold county by county, so a county search lists the plans a person in that county can choose from, where a state search lists every plan sold anywhere in the state.
  • The county code is the county’s five-digit FIPS code: two digits for the state and three for the county. A code that names no county is refused.
  • Find a county’s code by its name with the $counties operation, which lists a state’s counties and their codes:
    It answers a Parameters resource with one county parameter per county, sorted by name. Its code part is a Coding holding the county code, with the county’s name as its display, and its state part the state’s code. The list is the U.S. Census Bureau’s 2020 county codes.
  • A plan sold in only part of a county is listed for the whole county. A county search cannot tell which part of the county a person lives in, so the plan’s own documents are the place to check.
  • Employer and union group plans. In many counties most Medicare Advantage plans are sold only to employer and union groups: in Miami-Dade County, 731 of the 832 in the 2027 files. Add sold-to=individuals to list only the plans a person can buy on their own.
  • A regional PPO is sold in every county of its region’s states.

Paging

Every result is the whole plan, sorted by name and then id, and every page states the total. _count sets the page size, from 1 to 50, and is 10 by default; a larger value is refused rather than quietly reduced. Follow the link with relation next to continue. Its cursor belongs to that one search. If the plans are updated while you page, for example when a new plan year is loaded, the next page answers 410 and you start the search again, so a search never skips or repeats a plan without saying so.

Whether a provider is in a plan’s network

$in-network asks the CMS National Provider Directory, for up to 20 providers, whether it lists each one in a network the plan names, for the plan’s year:
Send each NPI as its own npi parameter, or several separated by commas. An NPI is ten digits, a practitioner’s or an organization’s; a duplicate counts once. The answer is a Parameters resource:
  • plan, the plan checked;
  • data-date, the day the directory last reloaded its record of the plan;
  • one network per network checked, with its name and organizations-listed, the number of organizations the directory lists in it;
  • reason, when the plan has no network data;
  • directory, a Marketplace plan’s own provider directory;
  • one provider per NPI, in the order sent, with its status and, when it is listed, an evidence reference to each listing, a PractitionerRole or an OrganizationAffiliation you can read on this base;
  • source, the directory, whenever it was asked.
The status codes and the reason codes are defined in the haau3 implementation guide. An answer for a Medicare Advantage plan, with illustrative NPIs and directory records:
And for a Marketplace plan, which the directory holds no network data for:
What an answer can and cannot tell you:
  • A listing is not a contract. in-network says the directory lists the provider in the plan’s network. Whether the provider takes the plan for a given service is for the plan and the provider to confirm.
  • not-found never means out of network. The directory’s network data is incomplete: many networks list no one yet. A provider not found may still be in the network.
  • Only the plan’s own year counts. A plan’s network can change between years, so a directory record for another year is not used, and the answer says so.
  • organizations-listed counts organizations only. The directory cannot count the practitioners a network lists, so a network listing no organizations may still list practitioners.
  • How fresh an answer is. Each answer asks the directory, and the directory’s answers are kept for up to a day, or up to an hour when nothing was found.
  • All or nothing. A lookup that fails fails the whole answer, with a 502, 503 or 504, never a partial list.
  • Usage. Each call counts as one Plan Benefits request; the directory lookups it makes are not counted as Provider directory requests.

What a plan contains

Every plan conforms to two profiles, and names both in meta.profile:
  • the haau3 Plan Benefits profile, https://haau3.com/fhir/StructureDefinition/haau3-insurance-plan, whose page states every rule in full; and
  • the SBC InsurancePlan profile of the CARIN Digital Insurance Card guide, hl7.fhir.us.insurance-card version 2.0.0-ballot.
In short:
  • Identity and type. identifier carries the plan’s ids, type its program, plan.type its network type (HMO, PPO and so on) with CMS’s own words, and ownedBy the issuer.
  • The release. An extension names the CMS release, and for each of CMS’s files its address, the date CMS last changed it and its SHA-256, so you can fetch the same file and check it.
  • Where it is sold. The plan’s states, searched with coverage-area-state. Its counties are searched with coverage-area-county and are not in the resource.
  • Plan facts. What each program files about a plan, such as a Marketplace plan’s metal level or a Medicare Advantage plan’s special needs type.
  • Deductibles and out-of-pocket maximums, in plan.generalCost, each scoped to a network, to one member or a family, and to medical care, drugs or both.
  • Costs of services, in plan.specificCost, each coded twice: the SBC benefit category and CMS’s own reference. Services the SBC categories have no code for, such as lab tests, home health care, hospital observation and a visit to a nurse or physician assistant, are in an extension shaped the same way.
A cost the files do not state is never written as $0. It carries a code saying why it has no amount, such as “not in the public files” or “not stated”, and a data-absent reason in place of the number. Some Medicare Advantage plans charge Original Medicare’s own amount for a deductible or a hospital stay; those costs say so and carry Original Medicare’s published amounts, labelled with their year.

What the public files do not hold

  • Marketplace premiums. They depend on the member’s age and where they live, and are not in these files. A Marketplace plan’s premium says so.
  • Plans from the state-run exchanges, such as California’s and New York’s. Only plans sold through HealthCare.gov are in the Marketplace files.
  • Which providers are in a network. A plan names its provider directory; the files do not list the providers. $in-network asks the CMS National Provider Directory instead.
  • A member’s own numbers, such as the visits used or how much of the deductible is met.
  • Drug-only and dental-only plans, and pharmacy benefits.

Errors

The statuses every service shares, among them 401, 405, 406, 415, 429 and 500, are on Errors, limits and request ids, which also says when to send a 502, 503 or 504 again, including inside a batch.

Data source and licensing

The plans are read from public files the Centers for Medicare & Medicaid Services publishes, a work of the U.S. Government: the PBP Benefits files and the Health Insurance Exchange Public Use Files, its Service Area file included. County names and codes are the U.S. Census Bureau’s 2020 county codes, also a work of the U.S. Government. $in-network reads network listings from the CMS National Provider Directory when asked. CMS does not endorse haau3.