04
Personalized Estimates
Learn how our API calculates a patient’s actual out-of-pocket cost for expensive, shoppable procedures. We layer a member’s current benefits and accumulators (deductible and out-of-pocket maximum) on top of our Standard Service Packages to calculate what they would actually owe.
Why this matters
A personalized estimate tells a patient what they will actually pay, so they can compare their real out-of-pocket costs before they book care. This matters most for patients on high-deductible plans facing coinsurance, or on plans with variable copay structures (such as lower copays at ambulatory surgery centers). We built this for shoppable procedures (e.g. colonoscopies) where a patient will actually compare options, and where a delta of a few hundred dollars can meaningfully impact their decision.
Our personalized estimates are best used for the following types of encounters:
- MRIs, CT, and imaging
- Colonoscopies & endoscopies
- Surgeries & ambulatory procedures
What you can build
The Consumer Pricing API can power your conversational AI patient experiences. Today these experiences return generic ranges that aren’t actionable. With the Consumer Pricing API, you can deliver the true cost of care, personalized to the patients’ insurance coverage.
Here are other ways to use personalized estimates via our API/MCP:
- Care navigation platform: Reveal a patient’s real after-insurance cost directly in your user experience.
- Digital Health companies: Show a patient what they’ll pay before booking their appointment.
- Referrals in EHRs: Surface estimates for patients alongside provider referrals
Networks and plans with cost share
Cost share calculations, i.e. how we generate personalized estimates, are live for a subset of payers and networks today and are not available yet for every network the API supports. We return negotiated rates for a much broader set of payers and networks, but we are expanding cost share coverage on a rolling basis. View the table below for a list of networks live today.
Blue Cross Blue Shield (30 plans)
- BCBS of Alabama – Preferred PPO
- BCBS of Arizona – PPO
- BCBS of Arkansas – True Blue PPO
- BCBS of Illinois – PPO
- BCBS of Maryland & DC (CareFirst) – PPO
- BCBS of Massachusetts – PPO
- BCBS of Michigan – PPO
- BCBS of Minnesota – Aware PPO
- BCBS of Mississippi – Preferred Provider Network
- BCBS of Nebraska – Networkblue PPO
- BCBS of New Jersey (Horizon) – Omnia
- BCBS of New Mexico – Preferred Provider Organization PPO
- BCBS of North Carolina – Preferred Provider Network
- BCBS of North Dakota – PPO
- BCBS of Pennsylvania (Independence) – KHPE Commercial HMO/POS
- BCBS of Pennsylvania (Independence) – QCC Commercial PPO/EPO
- BCBS of Rhode Island – PPO
- BCBS of South Carolina – Preferred Blue
- BCBS of Tennessee – Preferred
- BCBS of Texas – PPO
- BCBS of Vermont – PPO
- Blue Cross of Idaho – PPO
- Blue Shield of California – PPO
- Capital Blue Cross – PPO
- Premera Blue Cross – Alaska Heritage Network
- Premera Blue Cross – PBC PPO (Heritage) Network
- Regence Blue Cross Blue Shield – ID PPO
- Regence Blue Cross Blue Shield – OR PPO
- Regence Blue Cross Blue Shield – UT PPO
- Regence Blue Cross Blue Shield – WA PPO
How it works
We build each service into a Standard Service Package so every provider is priced on the same, apples-to-apples definition of the service and its ancillary components. See how we build packages on the pricing methodology page.
To turn a negotiated rate into a personalized estimate, we map the member's plan benefits to that package using our open-source benefit mapping logic, then apply their year-to-date accumulators (deductible and out-of-pocket maximum).
The benefit mapping logic takes the codes that would appear on a claim, or in this case within our Standard Service Package (SSP), and identifies the appropriate benefit category(s) to trigger. This logic contemplates bundling methodologies and other plan design nuances that impact downstream cost-share application (such as preventive benefits).
Plan-specific benefits and patient accumulator data are retrieved by running a 270/271 eligibility check with the member's payer, which returns their current benefits, eligibility, and accumulators, applied based on the service, provider, and place of service in question.
The EDI 270/271 transaction uses X12 language and operates on Service Type Categories (STCs) rather than procedure codes. Turquoise's logic bridges this gap: we translate STCs into the benefit adjudication logic at the billing code level. In practice, this means taking a Service Type Category, say STC 05 ("Labs"), and determining which CPT/HCPCS codes would be subject to that category's cost-share treatment.
See it in action
Let’s say Jane wants to know what a colonoscopy will cost her at Inova Fairfax Hospital,
and she has insurance through Cigna under the National OAP network. Here is how you would use
the API, with one call to POST /v3/personalized-estimates, to generate an
estimate for her.
Choose what you’re pricing
Start with a package and a network. For Jane, that is the colonoscopy package priced
against her Cigna National OAP plan. Because she only cares about Inova Fairfax, we
also pass provider_id to narrow the results to that one hospital. Omit
provider_id to get every provider and compare. These are the same
inputs you would use for a negotiated-rate lookup
(POST /v3/prices/query).
| Field | Meaning |
|---|---|
package_id (required) | The service you are pricing, e.g. a screening colonoscopy. |
pricing (required) | type: "negotiated" with a network_id. |
provider_id | Optional. Narrow the results to a single provider, like Inova Fairfax. |
location | Optional. Narrow by near, within, or zip. |
Add the member’s insurance details
The member_eligibility block identifies the patient we generate the
estimate for. In our case, Jane. This is PHI, so every request must attest
that the patient consented to the check.
| Field | Meaning |
|---|---|
first_name, last_name | The patient’s legal name. |
date_of_birth | The patient’s date of birth. |
member_id | The ID on the patient’s insurance card. |
consent_attested | Must be true — your attestation that the patient consented. |
The eligibility block is PHI. See HIPAA compliance for how it must be handled.
Call the endpoint
Now we send the package (colonoscopy), the pricing target (Cigna National OAP and
Inova Fairfax Hospital), and the member's eligibility (Jane's insurance details) to
POST /v3/personalized-estimates.
curl --request POST https://api.turquoise.health/v3/personalized-estimates \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/json" \
--data '{
"package_id": "pkg_01hxyz",
"pricing": { "type": "negotiated", "network_id": "482910" },
"provider_id": "prov_8821",
"member_eligibility": {
"first_name": "Jane", "last_name": "Doe",
"date_of_birth": "1990-01-01", "member_id": "MBR-000-EXAMPLE",
"consent_attested": true
}
}'
Note: the first query for a given patient returns a 202
“Eligibility check in progress, retry after a short delay”. The
real-time eligibility check can take a few seconds to run. Subsequent queries for the same
patient return a 200 with the information requested, and are faster because we cache the eligibility response.
Read the estimate
The response will contain a list of estimates, one per provider for the selected package and network. In this case, we have narrowed to Inova Fairfax, so the response only has one item. Jane's colonoscopy has a negotiated rate (total_allowed_amount) of
$2,400, and her share (user_cost_share) is $680.
200 OK
{
"items": [
{
"provider": { "id": "prov_8821", "name": "Inova Fairfax Hospital" },
"package": { "id": "pkg_01hxyz", "name": "Colonoscopy" },
"pricing": {
"type": "negotiated",
"network": { "id": "482910", "name": "Example PPO Network" },
"payer": { "id": "payer_01hxyz", "name": "Example Payer" }
},
"total_allowed_amount": { "amount": "2400.00", "minor_units": 240000, "currency": "USD" },
"user_cost_share": {
"total": { "amount": "680.00", "minor_units": 68000, "currency": "USD" },
"amount_towards_deductible": { "amount": "500.00", "minor_units": 50000, "currency": "USD" },
"amount_towards_copayment": { "amount": "0.00", "minor_units": 0, "currency": "USD" },
"amount_towards_coinsurance": { "amount": "180.00", "minor_units": 18000, "currency": "USD" },
"is_deductible_met": false,
"is_out_of_pocket_max_met": false
}
}
],
"benefits_summary": { /* see step 5 */ }
}
The response also returns a single benefits_summary, Jane's current accumulator state, so you can explain why a personalized estimate looks the way it does. Here she has not met her deductible, so most of the $680 goes toward it.
| Field | How to read it |
|---|---|
total | The number to show the patient. The three amounts below sum to this. |
amount_towards_deductible | How much of this service goes toward the not-yet-met deductible. |
amount_towards_copayment | The flat copay portion, if the plan charges one for this service. |
amount_towards_coinsurance | Their percentage share of the rest, after the deductible. |
is_deductible_met | true means the deductible is fully met at or after this service. |
is_out_of_pocket_max_met | true means the out-of-pocket maximum is met, so the plan covers everything beyond this. |
Every money value uses the standard Money shape: a string
amount ("680.00"), integer minor_units
(68000), and currency.
Understand the plan context
The response also returns a single benefits_summary,
Jane’s current accumulator state, so you can explain why a personalized
estimate looks the way it does. Here she has not met her deductible, so most of the
$680 goes toward it.
# benefits_summary, returned once alongside items[]
{
"remaining_deductible": 1200.00,
"total_deductible": 2000.00,
"remaining_out_of_pocket_max": 4800.00,
"total_out_of_pocket_max": 6000.00,
"deductible_accumulator_type": "individual",
"out_of_pocket_accumulator_type": "individual",
"benefit_categories": [
{ "category": "outpatient_surgery", "coinsurance": 0.20, "copayment": 0.00, "deductible": 2000.00 }
],
"limitations": []
}
| Field | How to read it |
|---|---|
remaining_deductible | The cap minus what the member has already spent. Jane’s $500 toward the deductible comes out of this; it is met once this hits 0. |
total_deductible | The full deductible for the year. Pair with remaining to show progress, e.g. “$800 of $2,000 met.” |
remaining_out_of_pocket_max | Dollars left before the plan covers everything. Once this hits 0, the member pays nothing more. |
total_out_of_pocket_max | The full out-of-pocket maximum for the year. |
deductible_accumulator_type, out_of_pocket_accumulator_type | How each accumulator resolves: embedded, aggregate, individual, or zero. |
benefit_categories[] | The per-category rules that applied. coinsurance is a rate (0.20 = 20%), plus copayment and a category deductible. |
limitations[] | Any plan limits, such as visit or dollar caps. Empty when none apply. |
Error messages
Calls to POST /v3/personalized-estimates can return the errors below. Most
are 422s tied to member matching or coverage, and their messages are written to be
shown to the patient so they can retry with corrected details.
| Error | HTTP | Message |
|---|---|---|
INVALID_MEMBER_ID | 422 | Member ID does not match the payer’s requirements. Retry with different member information. |
INVALID_DOB | 422 | We were not able to find your insurance with the date of birth provided. Retry with different member information. |
INVALID_MEMBER_NAME | 422 | We were not able to find your insurance with the name provided. Retry with different member information. |
MEMBER_NOT_FOUND | 422 | No member found matching the details provided. Retry with different member information. |
NO_ACTIVE_COVERAGE | 422 | A member was found but has no active coverage. Try again with different member information. |
UNSUPPORTED_TPA | 422 | This plan is managed by <tpa_name>, which is not currently supported. |
UNAVAILABLE_PAYER | 500 | The payer is temporarily unavailable. Please retry later. |
ELIGIBILITY_SERVICE_ERROR | 500 | Eligibility service error. An unexpected error occurred. |
PRICING_UNAVAILABLE | 503 | The pricing service is temporarily unavailable. Please retry later. |
INTERNAL_SERVER_ERROR | 500 | An unexpected error occurred. |
HIPAA compliance
Fields in
member_eligibility(first_name, last_name,
date_of_birth, and member_id) are Protected Health Information (PHI)
under HIPAA.
The demo environment does not accept live patient data, and no PHI may be exchanged. Production access is required to send real PHI to this endpoint and mandates a signed Business Associate Agreement (BAA) with Turquoise. Please contact us to enable production access.
Once in use, by setting consent_attested to true,
you represent to us that you obtained the patient's consent, consistent with your BAA.
This section is provided for informational purposes only and does not constitute legal advice. Please consult your own counsel to determine your organization's HIPAA obligations.