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"
statusFinancialResourceStatusCodesRequiredClaim adjudication status: ACTIVE, CANCELLED, DRAFT, ENTERED_IN_ERROR
identifierList<Identifier>OptionalClaim Number is the entry where type.coding[].code == "uc"
typeCodeableConceptOptionalClaim Type (Medical/Pharmacy/Dental/Vision/Lab) — code from system == "http://terminology.hl7.org/CodeSystem/claim-type"
useClaimUseCodesOptionalIntended use of the claim: CLAIM, PREAUTHORIZATION, PREDETERMINATION
patientReferenceOptionalMember Name is patient.display
billablePeriodPeriodOptionalService Date(s): start–end
createdStringOptionalClaim creation date; sort tiebreaker
providerReferenceOptionalProvider display is provider.display
outcomeRemittanceOutcomeCodesOptionalOne of three inputs for derived Claim Status: QUEUED, COMPLETE, ERROR, PARTIAL
paymentExplanationOfBenefitPaymentOptionalExplanationOfBenefitPayment.type is the third input for derived Claim Status
itemList<ExplanationOfBenefitItem>OptionalClaim line items; Description is item[n].productOrService.text or ...coding[0].display
totalList<ExplanationOfBenefitTotal>OptionalPowers Billed / Insurance Paid / You Paid

ExplanationOfBenefitTotal — filter category.coding[].code: "submitted" → Billed; "benefit" or "paidtopatient" → Insurance Paid; "paidbypatient" → You Paid.

ExplanationOfBenefitPayment fields

FieldTypeRequiredNotes
idStringOptionalUnique identifier for the payment record
typeCodeableConceptOptionalPartial vs. complete payment
amountMoneyOptionalPayable amount after adjustment
adjustmentMoneyOptionalPayment adjustment for non-claim issues (e.g., prior overpayment)
adjustmentReasonCodeableConceptOptionalExplanation for the adjustment
dateDateOptionalExpected date of payment

ExplanationOfBenefitItem fields

FieldTypeRequiredNotes
idStringOptionalUnique identifier for the item
sequenceIntOptionalPosition of this item in the claim
productOrServiceCodeableConceptOptionalSource of the claim-line Description — read .text, fall back to .coding[0].display
netMoneyOptionalTotal cost for this line item
quantityQuantityOptionalCount of products/services
revenueCodeableConceptOptionalRevenue or cost-center code
servicedDateDateOptionalDate of service for this line item
servicedPeriodPeriodOptionalDate range of service, when the item spans more than one day
modifierList<CodeableConcept>OptionalItem typification/modifier codes
bodySiteCodeableConceptOptionalAnatomical location where the service was performed
locationCodeableConceptCodeableConceptOptionalWhere the product or service was provided
noteNumberList<Int>OptionalNote numbers applicable to this item
adjudicationList<ExplanationOfBenefitAdjudication>OptionalItem-level adjudication detail

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?