Hospital price data, for developers

Patients Price publishes 1,062 hospitals, 476 procedures, and 333,874 hospital-published prices, taken from the machine-readable files hospitals must publish under federal law. If you are building a billing tool, a health copilot, or a benefits product, you can use that data two ways.

Free access, available now

The JSON API and MCP server are free and read-only:

One rule carries across everything we publish: a missing value means "not published" — never zero, never a guess. Every hospital page also shows the date of its price file, because files go stale.

Paid access, coming soon

We are planning paid tiers for machine buyers who need more than the free tier offers. Prices below are planned, not yet live — the waitlist at the bottom of this page is how we decide what to build first.

License

Free tier: use the data with attribution to Patients Price. Paid tiers: internal use. Redistribution, resale, or republication of the dataset needs a custom agreement — contact us and tell us what you're building.

Coverage and sample data

Coverage page: hospitals by state, most-covered procedures, and price-file freshness, queried live. Sample CSV: the 50 most-covered procedures, every hospital price we publish for them. Sample employer benchmark report: a Los Angeles example of what a regional report looks like, built from the live data.

Sample columns: procedure_code, procedure_name, hospital_name, hospital_state, setting, cash_price, gross_charge, neg_median, neg_min, neg_max, price_file_date. A missing value means "not published" — never zero, never a guess. Prices are whole dollars as published by hospitals; price_file_date is the date of that hospital's price file.

The human site, the financial-assistance guides, and the Learn hub stay free. Paid access is for machines buying data at machine speed, and it never includes anything about individual patients — the product is public price data.

Sample responses

Real responses, trimmed to one or two records. Full responses carry the same fields for every record.

GET /api/v1/procedures?q=colonoscopy

{"procedures": [{"code": "45378", "code_type": "HCPCS", "plain_name": "Colonoscopy", "hospitals": 770}, {"code": "45380", "code_type": "HCPCS", "plain_name": "Colonoscopy with biopsy", "hospitals": 770}]}

GET /api/v1/procedures/45378/rates

{"code": "45378", "count": 50, "rates": [{"hospital_id": "adventist-health-lodi-memorial-ca", "name": "Adventist Health Lodi Memorial", "state": "CA", "zip": "95240", "cash_price": 43.61, "gross_charge": 623.0, "neg_median": 410.4, "payer_count": 179}]}

GET /api/v1/hospitals?q=cedars

{"hospitals": [{"id": "cedars-sinai-medical-center-ca", "name": "Cedars Sinai Medical Center", "city": null, "state": "CA", "zip": "90048", "last_updated": "2025-11-26", "procedures": 313}, {"id": "providence-cedars-sinai-tarzana-medical-center-ca", "name": "Providence Cedars Sinai Tarzana Medical Center", "city": null, "state": "CA", "zip": "91356", "last_updated": "2026-04-01", "procedures": 324}]}

Note the city: null in the second sample: that hospital's file carries no city, so the API returns null instead of guessing one. A missing value always means "not published."

API reference

Base address: https://patientsprice.com. No key required, read-only, on a fair-use basis. All responses are JSON.

GET /api/v1/procedures?q= — Search procedures by plain words ("colonoscopy") or exact code ("45378"). The q parameter is optional; without it you get the 30 most-covered procedures. Returns up to 30 procedures, most-covered first. Each one carries code, code_type (CPT or HCPCS), plain_name, and hospitals — how many hospitals publish a price for it.

GET /api/v1/procedures/{CODE}/rates — Prices for one procedure. Parameters: state (two letters, optional, e.g. CA); zip plus radius_mi together (optional, for a distance search around a ZIP code, radius in miles); limit (optional, default 50, max 200); sort (optional: cash_price, gross_charge, neg_median, or neg_min; default cash_price, cheapest first, missing values last). Returns code, count (rates in this response), and rates: one row per hospital with hospital_id, name, city, state, zip, last_updated (that hospital's price-file date), cash_price, gross_charge, neg_min, neg_median, neg_max, payer_count, and distance_mi when a ZIP search is used. An unknown code returns an error naming the code.

GET /api/v1/hospitals?q= — Search hospitals by name or city words, or by an exact 5-digit ZIP code. The q parameter is required; an empty search returns an empty list. Returns up to 30 hospitals, by name. Each one carries id, name, city, state, zip, last_updated (price-file date), and procedures — how many procedures that hospital publishes prices for.

GET /api/v1/hospitals/{ID} — One hospital in full: the hospital row plus procedures, every procedure it publishes with code, plain_name, cash_price, gross_charge, neg_min, neg_median, and neg_max. An unknown id returns "hospital not found".

MCP server: POST /mcp — JSON-RPC 2.0, same data as the JSON API. Tools: search_procedures(query), get_procedure_rates(code, state, zip, radius_mi, limit, sort), and get_hospital(id). Parameters and limits match the JSON endpoints above.

The accuracy contract, in full: a missing value means "not published" — never zero, never a guess. Prices are whole dollars as published by the hospitals. A negotiated median blends every payer in that hospital's file; the free API does not split it by insurer. Every hospital row carries its price-file date, because files go stale — always check the date before quoting a price.

For enterprise buyers

If you need more than the free tier or the planned tiers above, we can build a custom arrangement:

Start at the contact page and tell us: your company, what you are building or buying for, which markets you need, and roughly how many lookups or records you expect. That is enough for a first conversation — no form, no account, just an email.

Join the waitlist

Tell us where to reach you when paid access opens. One email, when it is ready — nothing else.




We store only what you type above. No account, no tracking.