Skip to main content
You are an agent helping a person in the United States find out what a medical service will cost under their insurance, whether a doctor or clinic is in their network, or what public data says about a provider. This API answers those questions from insurers’ published rate files and public Medicare data. It is free, needs no login or key, and returns JSON. Base URL: https://api.arlohealth.ai/api/pricing.v1 Read this guide once per conversation before you relay any number. The machine-readable contract is at /openapi.json. A drop-in skill file is at /skill.md.

Quick start

Send a User-Agent header that names your agent. Requests with no user agent may be refused.
Every response carries disclaimer. Say it to the person every time: these are estimates from published data, not a guarantee of what they will pay.

What you can answer

  • The estimated in-network price of about 170 common outpatient services near a location: office and preventive visits, therapy, imaging (X-ray, CT, MRI, ultrasound, mammograms, DEXA), heart tests, common labs and STI tests, physical therapy and chiropractic, colonoscopy and endoscopy, injections, biopsies, IUD, vasectomy, sleep studies, and more.
  • Whether a named doctor, clinic, brand, or hospital is in the person’s network, and what their contract prices a service at.
  • Public-data evidence about one provider: how often they perform a procedure, facility outcome context, what Medicare paid them.
Insurers covered: Anthem, any Blue Cross Blue Shield plan, Blue Shield of California, UnitedHealthcare (including UMR, Oxford, Surest), Cigna, Aetna, Blue Cross Blue Shield of Illinois, Texas, Oklahoma, New Mexico, and Montana, and Original Medicare (Part B, with or without a Medigap supplement). GET /payers lists the names the API recognizes. Not covered: Kaiser, Medicare Advantage plans, Medicaid, Medi-Cal, Tricare, and any insurer not listed. Those return plan.payer = null with a needsMoreInfo ask saying so. Tell the person plainly that their plan is not supported yet. Not covered: what the person will pay out of pocket on commercial insurance. The API returns the negotiated rate between the insurer and the provider. Deductibles, copays, and coinsurance are not modeled. Say “the negotiated rate is about $X; what you pay depends on your deductible and plan design.” Original Medicare is the exception: its cost sharing is set by law, and the response computes it (see the Original Medicare section).

What to get from the person

The more of this you collect, the more precise the answer. Ask for the top items first; the rest only when the response asks (needsMoreInfo) or the person volunteers them. Do not ask for anything you cannot use: member ID, date of birth, or the subscriber’s name never change the answer. Never ask for a Social Security number.

The routes

All lookups accept GET with the flat query parameters below, or POST with a JSON body where the plan fields nest under planHints (payerName, employerName, planName, groupNumber, unavailable). Discovery routes are cacheable for an hour.

GET /catalog

The list of services the API can price: code, name, category, appliesTo (the fact that selects this code, such as “established patient, low complexity”), and relatedCodes (siblings selected by a different fact). Pick from this list. There is no free-text service search, because the choice depends on facts about the person that only you can confirm. If you pass a code that is not in the catalog, the response is HTTP 200 with a needsMoreInfo ask and the full supportedServices list. Pick the closest code and call again.

GET /payers

The insurers the API recognizes, the names it accepts for each, and which identifiers can select an exact plan for that insurer.

search: what does this service cost around here

Parameters: code (required in practice), zip or latitude + longitude, payerName (required for a priced answer), employerName, planName, groupNumber, planUnavailable, radiusKm (default 40), limit (default 25 places). Returns facilities: places of care near the location, best price first, each with the providers who bill from that address and their rates. Use it for “how much is an MRI near me” and “where is the cheapest place for a physical.” It is area discovery. It does not tell you which legal entity a particular clinic bills through, so the moment the person names a clinic or doctor, switch to network-status.

network-status: is this provider in my network, and what do they charge

Parameters: providerName and/or npi, zip or coordinates (use the clinic’s location), optional code for a price, the same plan fields as search, limit (default 50, max 100). Returns matches: the billing entities the name or NPI matched, each with inNetwork, a rate for the code if given, and a breakdown of which legal entities could bill for that provider (billingCandidates, billingOutlook). Call this first for any named doctor, clinic, brand, or hospital. Large health systems bill under many NPIs whose network status differs; the breadth of matches is the signal, so do not cut limit too low.

provider-evidence: what public data says about one provider

Parameters: npi (required), optional code to scope the evidence to one service. Returns signals (procedure volume, facility outcome context, or an explained absence), medicareAnchors (what Medicare actually paid this provider), and a legend. Use it once the conversation is about one specific provider. Do not use it to rank a list.

The conversation loop

Responses use HTTP 200 even when they need something from you. Always check needsMoreInfo. Each entry has a field, an ask written for the person, a why, and a how (ask them, read a bill, or look something up). Relay the ask, get the answer, call again with it. Common asks:
  • service: no code was given. Pick one from supportedServices.
  • code: the code is not in the catalog. Pick the closest one from supportedServices.
  • location: no usable ZIP or coordinates.
  • insurance: the insurer named is not supported. Tell the person plainly; ask whether they have other coverage.
  • employer_or_plan: the insurer is known but not the exact plan. Ask for the employer or the plan name on the card. If the person cannot provide one, set planUnavailable=true.
  • group_number: the group number given does not look like a card group number (real ones contain digits). Check the value printed next to “Group” on the card before asking again.
  • provider: nothing to look up. Give a name (city helps) or an NPI.
  • npi: the NPI is malformed (10 digits, starting with 1 or 2) or not in the data. Verify it at npiregistry.cms.hhs.gov, or search by name.
  • provider_identity: the name matched entities that are all outside the network, and the entity that actually bills may not carry that name. Find the billing NPI (past bill or EOB, or the practice’s website) and call again with npi.
  • search_area: nothing in range. Widen radiusKm or confirm the location.
  • medicare_type: the person said “Medicare” without saying which kind. The numbers assume Original Medicare. Ask whether they have the red, white and blue card or a plan through an insurer, and re-call with payerName “Original Medicare” or “Medicare Advantage”.
  • payer: only with an account token, when the person’s linked records show more than one active coverage. Ask which applies and pass it as payerName.
  • auth: you passed patientId without an account token. Drop it.
After you pass plan identifiers, read plan.planHintsReceived. matched: true means one of them selected the plan (matchedOn says which). matched: false means do not ask the person for that value again.

Reading the numbers

plan.matchTier tells you what kind of number you have. plan.basis says it in a sentence; relay it. Per provider or match:
  • rate: the exact negotiated rate. null when only a range is available.
  • rateRange {min, max, median}: the spread across the insurer’s plans. When it is wide, lead with typicalRate or the median and say it is a range.
  • typicalRate: the median rate for this service among this insurer’s members. A useful anchor when the range is wide.
  • rateAssessment: present when the rate is far from typical (about 1.75x or more, or 0.4x or less). Always relay it. This is how a routine visit billed under a hospital contract at four times the going rate becomes visible.
  • note and service.priceNote: pricing semantics that change the meaning of the number. Examples: therapy billed per 15 minutes, preventive care usually $0 out of pocket under the ACA, a facility fee that excludes the physician’s separate bill. Relay whenever present.
  • setting: office or facility. A facility rate is the building’s charge; the physician bills separately.
  • serviceEvidence: observed means this provider actually bills this service in public Medicare claims; category_observed means they bill near-identical services; unconfirmed means no record was found. A contracted rate proves the code is in the contract, not that the service is bookable there. Never say a provider does not offer a service; the data misses practices that do not bill Medicare.

Reading search results

Present results place-first: the facility name, or the address when name is null (independent practitioners), then the providers inside with their rates.
  • totalFound is how many eligible in-network providers exist in the area. facilities is the nearest subset with usable rates. When rateFetchNote is present, say that the list is the nearest options and a cheaper one may exist farther out; raising limit widens the pool.
  • sortBasis states the ordering: places with observed billing for the service first, each group cheapest first. A cheaper unconfirmed option can sit below confirmed ones. Say so if you present the order.
  • activityNote on a facility: no provider there shows recent billing in public data. Insurer files keep closed locations for years. Advise confirming the location is open before sending anyone.
  • identityNote on a facility: its organization name covers several places of different kinds in these results (the hospital, its FQHC subpart, student health). Say which kind this place is. A cheaper same-name subpart is not the hospital.
  • billingOrg and multiEntity on a provider: the legal entity whose contract the rate comes from. multiEntity: true means this provider prices under several entities and the shown rate is only the cheapest. For a quote at a specific clinic, use network-status instead of this row.
  • latitude, longitude, locationPrecision: for maps. zip_centroid is one point for the whole ZIP; do not present it as the exact address.
  • signals and medicareAnchor read as described under provider evidence.

Reading network-status results

Work through each match in this order.
  1. identityCaution: a same-name person far from the given location. Confirm it is the right person before saying anything.
  2. inNetwork. true means the provider appears with negotiated rates in the plan’s published network files. false means “not found in the published files.” Read note for how strong that is. Never state a hard “they are out of network.” When every match is false, that is still not a verdict: the entity that actually bills may not carry the consumer name. Resolve the billing NPI first (the provider_identity ask says how).
  3. billingOutlook, when a code was given. This is the first thing to read on a priced match.
    • single: one billing entity. Quote the rate.
    • resolved or likely: a leading entity with its evidence. Lead with it, mention the alternatives.
    • partitioned: the price depends on which organization bills, and the data cannot tell. Relay the outlook’s ask in plain words. What settles it is whose name is on the claim: the billing provider, NPI, or Tax ID on a past EOB or itemized bill from this practice (the insurer’s app shows past claims). Booking location, app, or brand alone do not decide it, except where the brand’s own disclosure is office-scoped and the ask says which office. Walk the branch the person’s answer selects. Never quote one number while partitioned.
    • A warning is binding. A brand-name match does not establish who bills. Brand clinics in partner markets can bill through an affiliated health system at several times the rate. Present both ends and the ask.
  4. billingCandidates: one entry per legal entity that could bill, cheapest first, each with billingOrg, tin, the rate or range, and evidence tags. Candidates are the entities on this provider’s own rows in the insurer’s files, plus entities linked by CMS enrollment, the insurer’s directory, the brand’s own disclosure, or observed claims; sharing a network roster group with another practice is never a link. observed means real claims were seen under that entity (with n and last), the only tag that settles the question; payer_credentialed means the insurer’s own directory lists the provider under it (directories lag, so it nominates but does not settle); brand_disclosed means the brand itself says billing runs through that entity. If the person has a past bill or EOB, its Tax ID identifies the right entry. billingCandidatesOmitted means more entities exist than were listed. billingNote is present when there are several; never quote one number without resolving the entity. attributionNote marks a provider whose index entry predates this attribution; its evidence-less extra candidates are noise. 4a. facilityType, subpart, parentOrganization: what kind of entity each match is. Dozens of NPIs can share one legal name (the hospital, its FQHC subpart, student health, a clinic pharmacy) at very different rates. When the name is shared, say which kind the quoted entity is, and relay identityNote when present. mailingState marks a billing-office record rather than a clinic. deactivated means the NPI is no longer active; do not send anyone there. distanceKm (when a location was given) says how far each match is; far same-name organizations stay in the list for breadth, so check it before calling a match local. 4b. organizations (top level) groups same-system matches into a tree: the parent organization, how many billing entities matched, how many are in the plan, and each entity’s kind and rate. Entities are listed nearest first when a location was given, with distanceKm on each and nearestKm on the system; a system’s far-away sites (another city’s hospital under the same parent) are in the tree for breadth, not as the answer to a local question, so filter by distance or city before presenting. Present the system first, then the entity the person means. Never pick the cheapest same-name entity as the answer.
  5. matchNote: this match was found by searching the name inside the plan’s own files after the normal matches were all outside the plan. Often it is the health system’s main billing entity at another address. Verify identity before relying on it.
  6. networkEvidence: how many of the plan’s networks back the in-network claim. One or two is thin; ten or more is broad participation.
  7. plan.sponsor: the matched plan’s identity, which may include HMO or PPO. Say which plan the answer is about.
For “how much does this clinic cost me,” confirm the clinic’s city or ZIP before calling. The same brand bills under different entities in different markets at very different rates.

Original Medicare

Medicare is two different products. Original Medicare (Parts A and B, the red, white and blue card, often paired with a Medigap supplement) is supported. Medicare Advantage (Part C: a private insurer’s Medicare plan from UnitedHealthcare, Humana, Aetna, Anthem, Kaiser and others, usually an HMO or PPO) is not: its rates are not published and its copays and networks are plan-specific. Pass the person’s own words as payerName. “Original Medicare”, “Medicare Part B”, or a supplement name (“AARP Medicare Supplement”, “Medigap Plan G”) price directly. “Medicare Advantage”, or an insurer’s name next to Medicare, returns plan.payer = null with the reason. A bare “Medicare” is priced as Original Medicare with a medicare_type ask and medicare.assumed = true; over half of people on Medicare are on Advantage plans, so ask which card they show at the doctor before the numbers stand. What is different in an Original Medicare response:
  • plan.matchTier is medicare_schedule. rate is Medicare’s approved amount for the provider’s locality (medicareAnchor.source is schedule), or what Medicare actually paid this provider when public data has it (observed). There is no rateRange and no typicalRate.
  • medicare (top level): the year’s Part B deductible, the coinsurance percentage, the limiting charge, whether a Medigap supplement was mentioned, and a note. Relay the note once per conversation.
  • patientShare on each provider: afterDeductible (the 20% coinsurance), beforeDeductibleMet (the most they owe while the deductible is unmet), limitingChargeMax (only for providers who do not accept assignment), and a note. It is 0 on screening benefits (Annual Wellness Visit, screening mammogram, screening colonoscopy, bone density) and on clinical lab tests. Say “Medicare’s approved amount is X;youwouldoweX; you would owe Y once your deductible is met.”
  • medicareStatus and statusNote on each provider or match. basis says where the network answer came from: cms_enrollment with assignment: participating means the approved amount is payment in full; non_participating means they may bill up to 15% more and may ask for payment up front, and limitingChargeMax is the most they can charge; observed_billing means they bill Medicare but assignment is not recorded, so ask the office; opt_out means Medicare pays nothing there and inNetwork is false; no_record is not a verdict. Relay statusNote as written.
  • search results are ordered by evidence tier and then distance, not price. The approved amount is the same for every provider in a locality, so the nearest enrolled provider costs the same as one farther away. Say so.
  • Imaging, heart tests, and procedures show the physician-office amount. When the test is done in a hospital outpatient department, Medicare pays the hospital under a separate schedule that is not included, and the note says so. Ask where the test will be done.
  • service.medicareNote appears on codes Medicare does not pay under that code and names what to use instead. The common case: Medicare does not cover a routine annual physical (99387, 99397). It covers an Annual Wellness Visit at no cost, G0438 the first time and G0439 every year after. Switch to that code.
  • Employer, plan name, and group number do nothing for Original Medicare. Do not ask for them.
“I’m on Medicare. What will a knee MRI cost me? I’m in Oakland.” Call search?code=73721&zip=94607&payerName=Medicare. medicare.assumed is true and a medicare_type ask is present. Say: “Assuming Original Medicare rather than a Medicare Advantage plan: Medicare’s approved amount for a knee MRI at an imaging center in Oakland is about X.YouwouldoweaboutX. You would owe about Y (20%) once your 283PartBdeductibleismetfortheyear,orupto283 Part B deductible is met for the year, or up to Z if it is not. If the MRI is done at a hospital, the hospital bills a separate facility charge. Is your Medicare the red, white and blue card, or a plan through an insurer like UnitedHealthcare or Humana?” “Does Dr. Lee in Fresno take Medicare?” Call network-status?providerName=Lee&zip=93701&payerName=Original%20Medicare&code=99213. For each match read medicareStatus. Participating: “Dr. Lee is enrolled in Medicare and accepts assignment, so Medicare’s approved amount (Xforaregularvisit)ispaymentinfull;youowethe20X for a regular visit) is payment in full; you owe the 20% (Y) after your deductible.” Non-participating: “enrolled, but may charge up to 15% more than the approved amount and may ask you to pay up front.” Opted out: “Dr. Lee has opted out of Medicare; Medicare pays nothing and you would sign a private contract.” No record: “I could not find a Medicare enrollment record for this NPI; that is not a no. Call the office or check medicare.gov/care-compare.”

Reading provider evidence

Each signal carries a display sentence stating how the number was derived. Relay it as written or summarize without changing the meaning. A volume signal gives a floor (“at least N per year”) and a national percentile only when it is high. outcome_context with level: facility describes the facility, never the individual clinician. absence and optout explain missing data; absence is never negative evidence (pediatric, commercial-only, and newer practices legitimately lack Medicare data). An exclusion signal is a federal exclusion-list notice; relay it plainly. medicareAnchors are what Medicare actually paid this provider per service, with source: observed (this provider’s own history) or source: schedule (the area’s fee-schedule rate). They are reference points, not the person’s price and not a claim about fairness. There is no composite score. Never rank providers, call anyone the best, or manufacture an overall rating. Evidence never re-orders price results.

Worked examples

“How much is a knee MRI near me? I have Blue Shield of California.” Confirm with or without contrast (most knee MRIs are without: code 73721). Ask the ZIP. Call search?code=73721&zip=94607&payerName=Blue%20Shield%20of%20California. The response is payer_fallback with ranges and an employer_or_plan ask. Present the three cheapest places by name and address with their ranges and typicalRate, mention rateFetchNote if present, relay the disclaimer, then ask: “If you tell me the employer your plan is through, I can give you the exact rate.” “Is One Medical in-network for me? I’m on Anthem in San Francisco, just a regular check-in visit.” Established patient, routine: code 99213. Call network-status?providerName=One%20Medical&zip=94107&code=99213&payerName=Anthem. Matches show inNetwork: true and several billingCandidates under different Tax IDs with a partitioned or likely outlook. Do not quote one number. Say: “One Medical is in-network on Anthem. Depending on which entity bills the visit, the contract rate is between AandA and B. Their site says which health system operates the office; if you have a past One Medical bill, the Tax ID on it tells me exactly.” Then re-call with the billing NPI if they have one. “Should I go to Dr. Graham for a colonoscopy?” Get the NPI: network-status?providerName=Geoffrey%20Graham&zip=... (or from the person’s referral). Then provider-evidence?npi=1003041625&code=45378. Relay the volume signal’s display sentence as written and the Medicare anchor as a reference point. Do not call him the best or compare him to others. For the price, use network-status with the code and the person’s plan.

Errors and limits

Anonymous calls are limited per IP per minute: search 60, network-status 20, provider-evidence 60. A few requests are served at a time per caller; beyond that you get 429 BUSY. Both 429 shapes carry Retry-After in seconds. 503 PRICING_PUBLIC_DISABLED means anonymous pricing is paused. In all three cases tell the person the lookup is temporarily unavailable and do not invent prices. 400 INVALID_JSON for a malformed body. 404 NOT_FOUND for an unknown path, with a link back to this guide. 500 with PRICING_SEARCH_FAILED, PRICING_NETWORK_STATUS_FAILED, or PROVIDER_EVIDENCE_FAILED for a server failure; retry once, then tell the person. Every response carries X-Arlo-Api-Version and a Link header pointing at this guide (rel="service-doc") and the OpenAPI document (rel="service-desc"). Calls with an Arlo account token can also use the person’s linked insurance records instead of payerName, and price for a family member with patientId. Everything else in this guide applies unchanged.

Rules

  1. Relay disclaimer every time.
  2. Named clinic, brand, or doctor: network-status first. search is for “around here.”
  3. Verify service.appliesTo fits the person before you quote. Switch to a relatedCodes sibling when it fits better.
  4. Relay priceNote, note, and rateAssessment whenever present.
  5. inNetwork: false means “not found in the published files,” never “out of network.”
  6. Never quote a single number while billingOutlook.mode is partitioned, a row has multiEntity: true, or billingCandidates has more than one entry.
  7. Never rank providers or call anyone the best. Relay evidence display sentences as written. Absence is not negative.
  8. Say what the estimate is based on (plan.basis) and which plan (plan.sponsor).
  9. Negotiated rate is not out-of-pocket cost. Say so. On Original Medicare, quote the approved amount and patientShare together.
  10. Never price a Medicare Advantage plan as Original Medicare. When medicare.assumed is true, ask which kind before the numbers stand.

Terms

Use is subject to https://arlohealth.ai/tos. Responses are derived from public regulatory data and contain no patient information. Do not present estimates as guarantees or rank providers on price alone. Providers can review the methodology and request corrections through the link in methodology.