Insurance Claims

Use the b.well Kotlin SDK to read a user's claims — service dates, billed/paid amounts, and claim status — for all plans or for one specific plan.

New to the SDK? See Initialize and Authenticate before making your first call.

What can you do?

📘 Related Documents

  • Filtering claims to one plan? You'll need a Coverage.id first — see Insurance Coverage.

Get all claims for the current user

Method Signature :

suspend fun getExplanationOfBenefits(request: ExplanationOfBenefitRequest?): BWellResult<ExplanationOfBenefit>


Example code :

val eobRequest = ExplanationOfBenefitRequest.Builder()
    .sort(listOf("-billablePeriod.start", "-created")) // Service date DESC
    .page(0)
    .pageSize(20)
    .build()

viewLifecycleOwner.lifecycleScope.launch {
    when (val result = BWellSdk.financials.getExplanationOfBenefits(eobRequest)) {
        is BWellResult.ResourceCollection -> {
            val claims = result.data ?: emptyList()
            println("Found ${claims.size} claim(s)")
        }
        else -> {
            println("getExplanationOfBenefits failed: ${result.error}")
        }
    }
}

📘 Notes

  • getExplanationOfBenefits returns a sealed BWellResult<ExplanationOfBenefit> — same pattern as getCoverages. Pattern-match with when; there is no .data() method.
  • .patient(patientId) / .patients(...) on the builder scope to one or more patients — omit to fetch everything the authenticated user can see.
  • An empty data list is a valid state (e.g. a brand-new plan with no claim history yet), not an error.

Get claims for one specific insurance plan

fun getClaimsForPlan(coverageId: String) {
    // coverageId is a bare Coverage.id from getCoverages — a "Coverage/"-prefixed
    // reference does not match. Requires b.well Kotlin SDK v1.18.0+.
    val eobRequest = ExplanationOfBenefitRequest.Builder()
        .coverage(coverageId)
        .sort(listOf("-billablePeriod.start", "-created"))
        .page(0)
        .pageSize(20)
        .build()

    viewLifecycleOwner.lifecycleScope.launch {
        when (val result = BWellSdk.financials.getExplanationOfBenefits(eobRequest)) {
            is BWellResult.ResourceCollection -> {
                val claims = result.data ?: emptyList()
                println("Found ${claims.size} claim(s) for this plan")
            }
            else -> {
                println("getExplanationOfBenefits failed: ${result.error}")
            }
        }
    }
}

📘 Notes

  • This is a second, distinct server-side request built with .coverage(coverageId) — it is not a client-side filter over the results of "Get all claims."
  • .coverage(coverageId) requires b.well Kotlin SDK v1.18.0 or later. On older versions the builder method doesn't exist.
  • An empty result here is indistinguishable from "plan has no claims yet" — both return an empty data list, not an error.

Sort claims by service date instead of last-updated time

.sort(listOf("-billablePeriod.start", "-created")) // service date DESC, tiebreak on created

📘 Notes

  • If .sort(...) isn't called, the request silently defaults to listOf("-meta.lastUpdated") — server write time, not Service Date. This does not match the b.well Insurance embeddable's default ordering.
  • Always set .sort(...) explicitly. -billablePeriod.start is the primary key (service date descending); -created breaks ties for claims with the same service date.

Read billed, insurance-paid, and you-paid amounts from a claim

val eob: ExplanationOfBenefit = /* one entry from the ResourceCollection above */

val billed = eob.total
    ?.firstOrNull { it.category?.coding?.any { c -> c.code == "submitted" } == true }?.amount

// Insurance Paid can appear under either code depending on the payor — check both
val insurancePaid = eob.total
    ?.firstOrNull { it.category?.coding?.any { c -> c.code == "benefit" || c.code == "paidtopatient" } == true }?.amount

val youPaid = eob.total
    ?.firstOrNull { it.category?.coding?.any { c -> c.code == "paidbypatient" } == true }?.amount

📘 Notes

  • Checking only "benefit" (or only "paidtopatient") for Insurance Paid misses claims from payors that use the other code — always check both in the same filter, as shown.

Determine claim status from outcome, status, and payment.type

val outcome = eob.outcome
val status = eob.status
val paymentType = eob.payment?.type

val claimType = eob.type?.coding
    ?.firstOrNull { it.system == "http://terminology.hl7.org/CodeSystem/claim-type" }
    ?.code // e.g. "medical", "pharmacy", "dental", "vision", "lab"

📘 Notes

  • There is no single field on ExplanationOfBenefit that represents a display-ready claim status — outcome, status, and payment.type are captured separately and combined by the caller.
  • For claim-type icons, key off code ("medical", "pharmacy", etc.), never type.coding[].display — display text isn't guaranteed to be stable across payors.

Reference


Result type cheat sheet

MethodReturnsHow to read it
BWellSdk.financials.getExplanationOfBenefits(...)BWellResult<ExplanationOfBenefit>Pattern-match with when or as?. is BWellResult.ResourceCollection.data: List<ExplanationOfBenefit>?. Any other branch → .error: OperationOutcome.

ExplanationOfBenefitRequest fields

Builder methodRequired?Notes
.patient(patientId) / .patients(...)OptionalScope to one or more patients
.coverage(coverageId) / .coverages(...)OptionalScope to claims tied to one or more Coverage ids — requires SDK v1.18.0+
.id(...) / .ids(...)OptionalFetch specific claim(s) by id
.lastUpdated(...)OptionalFilter by server last-write time
.sort(List<String>)OptionalFHIR _sort tokens; - prefix = descending. Defaults to ["-meta.lastUpdated"] if omitted — see notes above
.page(n) / .pageSize(n)OptionalPagination — defaults to 0 / SDK standard page size

ExplanationOfBenefit response shape

FieldTypeRequiredNotes
idStringRequiredUnique identifier
resourceTypeStringRequiredAlways "ExplanationOfBenefit"
metaMetaOptionalResource metadata
identifierList<Identifier>OptionalClaim Number is the entry where type.coding[].code == "uc"
statusFinancialResourceStatusCodesRequiredClaim adjudication status
typeCodeableConceptOptionalClaim Type (Medical/Pharmacy/Dental/Vision/Lab) — code from system == "http://terminology.hl7.org/CodeSystem/claim-type"
subTypeCodeableConceptOptionalAdditional classification of the claim type
useClaimUseCodesOptionalIntended use of the claim
patientReferenceOptionalMember Name is patient.display
billablePeriodPeriodOptionalService Date(s): startend
benefitPeriodPeriodOptionalPeriod during which the benefit coverage is active
createdStringOptionalClaim creation date; sort tiebreaker
insurerReferenceOptionalParty responsible for the claim
providerReferenceOptionalProvider display is provider.display
outcomeRemittanceOutcomeCodesOptionalOne of three inputs for derived Claim Status
dispositionStringOptionalHuman-readable description of the adjudication status
careTeamList<…>OptionalMembers of the care team
diagnosisList<…>OptionalClinical diagnoses relevant to the claim
insuranceList<…>OptionalInsurance coverages relevant to the claim. insurance[].coverage is what .coverage(coverageId) filters on
itemList<ExplanationOfBenefitItem>OptionalClaim line items; Description is item[n].productOrService.text or ...coding[0].display
adjudicationList<…>OptionalAdjudication detail at the claim level. Distinct from item[].adjudication, which is per line item
totalList<ExplanationOfBenefitTotal>OptionalPowers Billed / Insurance Paid / You Paid
supportingInfoList<…>OptionalSupporting information relevant to the claim
paymentPaymentOptionalpayment.type is the third input for derived Claim Status
payeeReferenceOptionalParty receiving payment
relatedList<…>OptionalRelated claims that may be relevant to processing this claim
processNoteList<…>OptionalNote text associated with claim processing

📘

Claim-level vs item-level adjudication

ExplanationOfBenefit.adjudication and ExplanationOfBenefitItem.adjudication are separate lists. Claim-level adjudication describes the claim as a whole; item-level adjudication describes one line. Reading one when you meant the other is a common source of totals that do not reconcile.


ExplanationOfBenefitTotal

FieldTypeNotes
categoryCodeableConceptFilter by category.coding[].code. "submitted" is Billed; "benefit" or "paidtopatient" is Insurance Paid; "paidbypatient" is You Paid
amountMoneyTotal amount for this category

ExplanationOfBenefitItem

FieldTypeNotes
idStringUnique identifier for the item
sequenceIntPosition of this item in the claim
productOrServiceCodeableConceptProduct or service provided. Source of the claim-line Description
noteNumberList<Int>Note numbers that apply to this item
adjudicationList<…>Adjudication detail for this item
bodySiteCodeableConceptAnatomical location where the service was performed
locationCodeableConceptCodeableConceptWhere the product or service was provided
modifierList<CodeableConcept>Item typification or modifier codes
netMoneyTotal item cost
quantityQuantityCount of products or services
revenueCodeableConceptRevenue or cost center code
servicedDateStringDate of service or product delivery
servicedPeriodPeriodDate range of service or product delivery

Annotated shape

{
  "id": "eob-77213",
  "resourceType": "ExplanationOfBenefit",
  "status": "active",
  "type": { "coding": [
    { "system": "http://terminology.hl7.org/CodeSystem/claim-type", "code": "medical" }
  ]},
  "patient": { "display": "Jordan Smith" },
  "provider": { "display": "Dr. Alicia Chen" },
  "billablePeriod": { "start": "2026-03-04", "end": "2026-03-04" },
  "created": "2026-03-10",
  "identifier": [
    { "type": { "coding": [{ "code": "uc" }] }, "value": "CLM-556213" }
  ],
  "total": [
    { "category": { "coding": [{ "code": "submitted" }] }, "amount": { "value": 420.00 } },
    { "category": { "coding": [{ "code": "benefit" }] }, "amount": { "value": 336.00 } },
    { "category": { "coding": [{ "code": "paidbypatient" }] }, "amount": { "value": 84.00 } }
  ]
}

Troubleshooting


Each heading below is the symptom or error you may encounter. Search this section for the closest match to what you're hitting.

Issue: Does not compile: data is not a member of BWellResult<ExplanationOfBenefit> You accessed .data before narrowing to BWellResult.ResourceCollection.
Fix: Pattern-match with when or as? first.

Issue: getExplanationOfBenefits returns an error result where it used to succeed The session is missing or expired.
Fix: Check the non-ResourceCollection branch and inspect result.error. Re-run SDK initialization/authentication and retry.

Issue: Claims come back in the wrong order .sort(...) wasn't called, so the request silently used the default -meta.lastUpdated order instead of Service Date.
Fix: Always pass .sort(listOf("-billablePeriod.start", "-created")) explicitly.

Issue: .coverage(coverageId) has no effect, or the build fails The Coverage-filtered request requires b.well Kotlin SDK v1.18.0 or later. On older SDK versions the builder method is unavailable.
Fix: Confirm the SDK version in use before adopting the plan-filtered claims flow.

Issue: Insurance Paid amount looks wrong or missing Filtering total for only "benefit" (or only "paidtopatient") misses claims from payors that use the other code.
Fix: Check both "benefit" and "paidtopatient" in the same filter.

Issue: Claim-type icon doesn't match the claim The icon logic reads type.coding[].display instead of code, and display text varies by payor.
Fix: Key icon selection off code from the http://terminology.hl7.org/CodeSystem/claim-type system, never display.

If your issue isn't listed here, reach out to support and include: the SDK version, the exact ExplanationOfBenefitRequest builder calls used, and the full OperationOutcome from result.error if the failure branch was hit.


Did this page help you?