Home / Tools / Hospital price transparency

Hospital price transparencyL2 · v1.10.0 · read-only

compare_hospital_rates

Compare Hospital Rates

What it answers

Compares what a billing code costs ACROSS hospitals (cheapest real price first) with a p10/median/p90 benchmark AND a per-(payer x line-of-business) breakdown. The product query for 'where is care cheapest' and 'what does each payer actually pay'. Reads the canonical serving view `vlada_curated.vw_fact_hospital_chargemaster_canonical`, which resolves each raw payer string to its REAL parent entity (the canonical payer graph) and classifies each plan to a regulatory line-of-business (commercial / medicare_advantage / medicaid / marketplace / ...). Inputs: billing_code (required), state (optional 2-letter), code_system (optional), billing_class (default 'institutional' = facility/UB-04; or 'professional'/'both'; classes are never mixed -- since 1.6.0 'institutional'/'professional' each WIDEN to include billing_class_resolved='both' rows, a charge posted on both the facility and professional side of a bill per the HPT schema; pass 'institutional_only'/'professional_only' for the strict single-class stratum), limit (default 25), payer (optional brand OR parent, e.g. 'Aetna' or 'CVS Health'), line_of_business (optional, e.g. 'medicare_advantage'). Each returned rate carries the view's canonical payer columns (`payer_canonical_id`, `payer_parent_name`, `payer_entity_class`, `payer_match_method`) plus `line_of_business` so a comparison is apples-to-apples (Aetna-MA != Aetna-Commercial). `value.by_payer_lob` is the 'rates across all the payers' table. CROSS-SUBSTRATE: every rate also carries x_medicare (the multiple of the Medicare allowed amount: PFS national non-facility for professional, OPPS APC for outpatient institutional, IPPS MS-DRG national base for inpatient DRG codes); `value.medicare` holds the allowed amount + schedule + year, so the answer is 'this payer pays 1.6x Medicare at this hospital'. VALIDATION (load-bearing): billing_class is normalized + inferred from code_system/rate_type where the source omits it; only the requested class is compared; class-implausible rates (e.g. $0.007 for a CT) and code-relative outliers are filtered. CHEAPEST HEADLINE (1.2.0): `value.cheapest` is ranked over rows PLAUSIBLE for the code's Medicare basis -- when the allowed amount is a real procedure (>= $500) a row under 0.3x Medicare (the comparability cascade's own lower sane bound) is set aside into `value.implausible_tail` (full rows + floor + reason, never deleted; benchmark still includes it), and the rest rank hospital-stated methodology (fee_schedule/case_rate/per_diem) before methodology-unknown, rate ascending within each tier -- read `plausibility` + `rank_tier` on each row. Under the $500 gate (imaging / visits / labs) no floor applies, so a $44 head CT still headlines. CASE-RATE HEADLINE (1.7.0): on a DRG/case-rate seat the floor is 0.5x (not 0.3x -- an inpatient rate below half of IPPS is not credible as the full case price), and `cheapest` headlines hospital-STATED case_rate rows ONLY when at least one survives the floor; methodology-unknown rows are demoted into `value.implausible_tail` (tail_reason='methodology_unknown_demoted') even when they themselves clear the floor. `cheapest` headlines an unknown row only when NO stated row survives, and a `headline_methodology_unknown` warning caveat says so. ONE CODE SYSTEM PER WINDOW (1.3.0): `cheapest` holds rows of the seated code system only (`value.code_system_resolved`, the dominant system or the caller's `code_system`), each row stamped `code_system`; when the floor empties a full window the tool re-asks once for rows at or above the floor rate (`value.cheapest_window.second_pass`), and if `cheapest` still ends empty a `no_plausible_rows_in_window` caveat says why. ONE METHODOLOGY FAMILY PER WINDOW (1.4.0): within the seated code system, `cheapest` and the re-seated `value.benchmark` / `comparable_benchmark` are further restricted to ONE methodology family -- fee_schedule (a line, the natural family for CPT/HCPCS/APC/RC), case_rate (an admission, the natural family for a DRG/MS-DRG seat), or per_diem (a day) -- because a case rate, a per diem and a fee schedule price different economic objects and must never share a median or a ranked list. `methodology_family` (optional: fee_schedule|case_rate|per_diem) overrides the natural seat. Rows the hospital stated in a DIFFERENT family are set aside into `value.other_family`, in full, never blended in; `value.by_methodology_family` reports n/n_hospitals/p10/median/p90 for every family present, and a `methodology_families_mixed` caveat fires when more than 10% of the population sits outside the seated family. BY_METHODOLOGY RECONCILES (1.6.1): `value.by_methodology` (percent_of_charge/fee_schedule/case_rate/per_diem/other/unknown, with median_rate_over_gross_charge) is narrowed to the SAME population `value.benchmark.n` reports -- sum(by_methodology[].n) == benchmark.n, ALWAYS, by construction; the unstratified, every-family view (within the seated code system) is `value.by_methodology_all_families`, which is what `value.percent_of_charge_share` and the `methodology_mix` caveat read (percent_of_charge rows are always 'unknown' family and would otherwise be invisible once a family is seated). SOURCE: CMS Hospital Price Transparency MRFs (45 CFR 180.50) + CMS Medicare PFS/OPPS fee schedules. KNOWN GAPS: not geo-aware beyond state; payer resolution covers ~80.9% of volume and line-of-business ~85.7% (measured on the 70553 probe, 2026-08-13; call coverage_status for live counts), unmatched rates fall to '(unresolved)'/'unspecified'; bare Blue-family labels (e.g. 'Bcbs') are bucketed '(blue family: label too generic to attribute)' with payer_resolution='generic_label' and never attributed to a specific Blue parent; IPPS DRG x_medicare is the national base (excludes wage index/IME/DSH/outliers); x_medicare null for revenue/non-HCPCS CDM codes; ghost-rate filter is heuristic. DRG GROUPER PRECISION (1.5.0): MS-DRG, APR-DRG and AP-DRG are different maintainers with different numbering (MS-DRG 470 = joint replacement, APR-DRG 470 = chronic kidney disease) and only MS-DRG prices against the IPPS base; the served mart still collapses all of them into one bare 'DRG' code system, so `value.medicare.precision` reads 'drg_grouper_unknown' (with a warning caveat) on that seat until the code_system_resolved bucket split rebuild lands, and 'exact' otherwise. BOTH-CLASS DEFAULT STRATUM (1.6.0): billing_class 'institutional'/'professional' each widen to include billing_class_resolved='both' rows (a charge the HPT schema posts for both sides of a bill); every row still carries its own resolved `billing_class`, and a `both_class_rows_included` caveat states the measured count whenever the answer includes at least one such row. Measured on CT (2026-08-18): 9.63% of REAL_NEGOTIATED rows are 'both', 100% with no institutional sibling row -- previously invisible at the old strict-institutional default. Pass 'institutional_only'/'professional_only' for the pre-1.6.0 strict single-class stratum.

Inputs

billing_code
string · required
billing_class
string · optional
default: "institutional"
code_system
any · optional
default: null
comparable
any · optional
default: null
facility_type
any · optional
default: null
limit
integer · optional
default: 25
line_of_business
any · optional
default: null
methodology
any · optional
default: null
methodology_family
any · optional
default: null
payer
any · optional
default: null
state
any · optional
default: null

Call it

From an agent: connect the Vlada MCP once (one click for Claude, ChatGPT, Cursor, VS Code) and ask in plain English; the agent selects compare_hospital_rates when the question fits. From code: the same tool over REST with an API key. The schema endpoint needs no key.

curl -X POST https://api.vladahealth.com/v1/tools/compare_hospital_rates \
  -H "Authorization: Bearer $VLADA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"billing_code":"<billing_code>"}'
curl https://api.vladahealth.com/v1/tools/compare_hospital_rates/schema      # the JSON schema, no auth
# MCP endpoint (Streamable HTTP): https://mcp.vladahealth.com/mcp

What comes back

Typed rows plus provenance on every answer: the public source file, its vintage, the methodology, and a response_hash you can replay. Prove and replay tools turn any number into a re-runnable receipt. A number the data cannot support comes back as “not in the data”, never as zero.

Output schema
{
 "$defs": {
  "Quality": {
   "description": "Row-level quality signal. All flags precomputed at build time\n(stored on the gold mart) and passed through here.",
   "properties": {
    "is_outlier": {
     "default": false,
     "title": "Is Outlier",
     "type": "boolean"
    },
    "is_ghost_candidate": {
     "default": false,
     "title": "Is Ghost Candidate",
     "type": "boolean"
    },
    "n_similar_rates": {
     "default": 0,
     "title": "N Similar Rates",
     "type": "integer"
    },
    "confidence": {
     "default": 1,
     "title": "Confidence",
     "type": "number"
    }
   },
   "title": "Quality",
   "type": "object"
  },
  "Source": {
   "description": "Cell-level provenance. Every served value traces back here.\n\n`snapshot_id` is the Iceberg snapshot the tool read from. Two calls\nat the same snapshot MUST produce byte-identical responses —\nthat's the content-addressed caching guarantee.",
   "properties": {
    "table": {
     "title": "Table",
     "type": "string"
    },
    "rate_id": {
     "anyOf": [
      {
       "type": "string"
      },
      {
       "type": "null"
      }
     ],
     "default": null,
     "title": "Rate Id"
    },
    "source_files": {
     "items": {
      "type": "string"
     },
     "title": "Source Files",
     "type": "array"
    },
    "snapshot_id": {
     "anyOf": [
      {
       "type": "integer"
      },
      {
       "type": "null"
      }
     ],
     "default": null,
     "title": "Snapshot Id"
    }
   },
   "required": [
    "table"
   ],
   "title": "Source",
   "type": "object"
  }
 },
 "description": "Value carries {billing_code, state, billing_class, cheapest[], benchmark}.",
 "properties": {
  "value": {
   "default": null,
   "title": "Value"
  },
  "unit": {
   "anyOf": [
    {
     "type": "string"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "Unit"
  },
  "vintage": {
   "anyOf": [
    {
     "type": "string"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "Vintage"
  },
  "source": {
   "$ref": "#/$defs/Source"
  },
  "methodology": {
   "anyOf": [
    {
     "type": "string"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "Methodology"
  },
  "quality": {
   "$ref": "#/$defs/Quality"
  },
  "invariants_applied": {
   "items": {
    "type": "string"
   },
   "title": "Invariants Applied",
   "type": "array"
  },
  "caveats": {
   "items": {
    "type": "string"
   },
   "title": "Caveats",
   "type": "array"
  },
  "response_hash": {
   "default": "",
   "title": "Response Hash",
   "type": "string"
  },
  "semantic_version": {
   "default": 1,
   "title": "Semantic Version",
   "type": "integer"
  },
  "tool_version": {
   "default": "unknown",
   "title": "Tool Version",
   "type": "string"
  },
  "explanation": {
   "anyOf": [
    {
     "type": "string"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "Explanation"
  },
  "status": {
   "default": "complete",
   "title": "Status",
   "type": "string"
  },
  "refusal": {
   "anyOf": [
    {
     "additionalProperties": true,
     "type": "object"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "Refusal"
  },
  "failure": {
   "anyOf": [
    {
     "additionalProperties": true,
     "type": "object"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "Failure"
  },
  "as_of": {
   "anyOf": [
    {
     "type": "string"
    },
    {
     "type": "null"
    }
   ],
   "default": null,
   "title": "As Of"
  },
  "freshness_state": {
   "default": "unknown",
   "title": "Freshness State",
   "type": "string"
  }
 },
 "title": "CompareHospitalRatesResponse",
 "type": "object"
}

Sources behind it

  • vlada_curated.vw_fact_hospital_chargemaster_canonical

tables: vlada_curated.vw_fact_hospital_chargemaster_canonical

Known limits

  • hospital_billing_class_inferred
  • hospital_geo_state_only
  • hospital_ghost_rate_filter_heuristic

As of the 2026-09-19 build of the served surface · machine-readable catalog · the live server may run a different version; the schema endpoint above is authoritative for what is deployed.