Schema Care

The FHIR ExplanationOfBenefit Resource for Developers

By Schema CarePublished Updated

The FHIR ExplanationOfBenefit resource records how a payer settled a claim: what was billed, what the plan allowed, what it paid and what the patient owes, line by line. It joins the Claim request and the payer's decision in one resource, which makes it the natural FHIR target for data read from a printed EOB.

What is the FHIR ExplanationOfBenefit resource for?

The FHIR ExplanationOfBenefit resource is a summary of one adjudicated claim, written for patients and the apps that serve them. The FHIR R4 ExplanationOfBenefit page says it combines key information from a Claim, a ClaimResponse and optional Account information, and describes the services rendered and how the payer settled them.

The same page sets out who it is for. It is meant for reporting to patients, for moving data into patient-centered apps, and for bulk analytics. Provider-specific and payer-specific details are stripped out, so the specification prefers ExplanationOfBenefit over the Claim and ClaimResponse pair when the audience is a patient. For claims history shown to a patient, that preference points to ExplanationOfBenefit rather than raw claims.

For a developer, the resource answers a narrow question: for this claim, what happened to each charge? It does not replace the transaction that told a provider about the payment. The R4 page states that ExplanationOfBenefit shall not be used as a replacement for a ClaimResponse. A billing system that posts payments still works from the remittance it received. The ExplanationOfBenefit is the shareable, readable record of the outcome.

The resource also has a place in a document pipeline. When a practice or a patient has only a paper or PDF EOB, the fields on that page can be mapped into an ExplanationOfBenefit so that the claim outcome sits next to other FHIR data. Which resource each kind of paperwork should become is a broader question, covered in the guide to which FHIR resources match each medical document type. The meaning of each printed column on the page itself is explained in how to read an EOB, line by line.

Schema Care reads printed EOBs into structured fields such as service lines, allowed amounts, plan payments and remark codes, and you can see the document types Schema Care reads on the homepage. Schema Care offers no API, SDK, webhooks, FHIR output, 835 output or 837 output, so it produces no ExplanationOfBenefit resources and the mapping in this post is work your own code would do.

ExplanationOfBenefit versus the FHIR Claim resource

The FHIR Claim resource is the request and ExplanationOfBenefit is the adjudicated result. A Claim asks a payer to pay for, authorize or estimate services. An ExplanationOfBenefit reports what the payer decided, carrying the requested amounts alongside the allowed, paid and patient amounts.

The FHIR R4 Claim resource page names three uses for a Claim. A claim is sent when the goods and services are complete and payment is sought. A preauthorization is sent when they are proposed. A predetermination explores what may be covered. The payer's answer to any of these is a ClaimResponse, which the same page describes as a payer's adjudication or authorization response to the services in a Claim.

ExplanationOfBenefit sits across both. The Claim page says to use it when both the request and the adjudication must be reported, and it is the preferred resource for patient-facing reporting. That is the case with a printed EOB: the page shows the billed charge, which came from the provider's claim, next to the allowed amount and plan payment, which came from the payer.

The two resources share a lot of shape. Both have status, type, use, patient, created, provider and insurance, and both list services as item entries with a sequence and a productOrService code. The Claim requires priority, which ExplanationOfBenefit does not. ExplanationOfBenefit adds the payer side: an insurer, an outcome, adjudication on each item, total amounts and a payment block.

When do you need both? If you are building a system that submits claims through FHIR, you create Claim resources and read back ClaimResponse resources. If you are publishing or storing what a payer decided, especially from paperwork that never passed through your system as a Claim, ExplanationOfBenefit alone is enough. A paper EOB rarely gives you the full original claim, so building a Claim from it would mean inventing fields the page does not show.

EOB fields mapped onto items and adjudication

Each printed EOB field has a home in ExplanationOfBenefit. Claim-level facts go on the resource itself: patient, insurer, claim number, dates. Each service line becomes one item, and each money column on that line becomes one entry in the item's adjudication list, coded by a category such as submitted, eligible, deductible or benefit.

The item is the core of the mapping. The R4 page gives each item a sequence and a productOrService code, both required, plus optional serviced[x] for the date, quantity, unitPrice and net. Each item can carry its own adjudication entries, and items can nest detail and subDetail tiers when a payer reports below the line level.

An adjudication entry has a required category, an optional reason, and either an amount or a value, which the specification says are mutually exclusive. The base specification's adjudication value codes include submitted, eligible, deductible, copay, benefit and a few more. It has no coinsurance code. The CARIN Blue Button guide adds one in its C4BB adjudication code system, along with codes such as noncovered, paidtoprovider and memberliability.

Worked example: one fictional EOB line as an ExplanationOfBenefit

This example uses a made-up EOB for a made-up patient, Jordan Example, member ID EXM000111 (example), claim number EX-2026-0412 (example). The single line is an office visit billed at $250.00 (example) with a $90.00 contractual adjustment, $160.00 allowed, $40.00 to deductible, $24.00 coinsurance and a $96.00 plan payment.

Printed EOB field (example value)ExplanationOfBenefit element
Claim number EX-2026-0412identifier[0].value
Patient Jordan Examplepatient (a reference to a Patient resource)
Member ID EXM000111the Coverage resource referenced by insurance[0].coverage
Payer name Example Health Planinsurer (a reference to an Organization)
Rendering providerprovider (a reference to a Practitioner or Organization)
Date of service 2026-08-04item[0].servicedDate
Procedure code 99213item[0].productOrService
Billed $250.00item[0].adjudication with category submitted
Allowed $160.00item[0].adjudication with category eligible
Adjustment CO-45, $90.00item[0].adjudication with a reason code and amount
Deductible $40.00item[0].adjudication with category deductible
Coinsurance $24.00item[0].adjudication with the CARIN coinsurance code
Plan paid $96.00item[0].adjudication with category benefit
Claim totalstotal entries using the same categories
EOB date 2026-08-20created

Here is the same example as JSON. Every identifier, name and amount is fictional, and the referenced Patient, Organization and Coverage resources are assumed to exist on the same server.

{
  "resourceType": "ExplanationOfBenefit",
  "status": "active",
  "type": {
    "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/claim-type", "code": "professional" }]
  },
  "use": "claim",
  "identifier": [{ "system": "urn:example:payer-claim-number", "value": "EX-2026-0412" }],
  "patient": { "reference": "Patient/example-jordan" },
  "created": "2026-08-20",
  "insurer": { "reference": "Organization/example-health-plan" },
  "provider": { "reference": "Organization/example-clinic" },
  "outcome": "complete",
  "insurance": [{ "focal": true, "coverage": { "reference": "Coverage/example-exm000111" } }],
  "item": [{
    "sequence": 1,
    "productOrService": {
      "coding": [{ "system": "http://www.ama-assn.org/go/cpt", "code": "99213" }]
    },
    "servicedDate": "2026-08-04",
    "adjudication": [
      { "category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "submitted" }] },
        "amount": { "value": 250.00, "currency": "USD" } },
      { "category": { "coding": [{ "system": "http://hl7.org/fhir/us/carin-bb/CodeSystem/C4BBAdjudicationDiscriminator", "code": "adjustmentreason" }] },
        "reason": { "coding": [{ "system": "https://x12.org/codes/claim-adjustment-reason-codes", "code": "45" }] },
        "amount": { "value": 90.00, "currency": "USD" } },
      { "category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "eligible" }] },
        "amount": { "value": 160.00, "currency": "USD" } },
      { "category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "deductible" }] },
        "amount": { "value": 40.00, "currency": "USD" } },
      { "category": { "coding": [{ "system": "http://hl7.org/fhir/us/carin-bb/CodeSystem/C4BBAdjudication", "code": "coinsurance" }] },
        "amount": { "value": 24.00, "currency": "USD" } },
      { "category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "benefit" }] },
        "amount": { "value": 96.00, "currency": "USD" } }
    ]
  }],
  "total": [
    { "category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "submitted" }] },
      "amount": { "value": 250.00, "currency": "USD" } },
    { "category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "benefit" }] },
      "amount": { "value": 96.00, "currency": "USD" } }
  ]
}

A few choices in the example deserve a note. The CPT system URI comes from the FHIR R4 list of external code systems. The adjustment entry follows the CARIN pattern, where an adjustmentreason category carries the reason code, and the CARIN guide's CARC and RARC value set names the X12 code list URL used here. What CO-45 means, and how the group code assigns responsibility, is explained in the guide to claim adjustment reason codes on an EOB. How code systems such as CARC, CPT and LOINC are identified across extracted data is the subject of the post on which code systems appear in extracted medical data.

The amounts in the example also balance: $250.00 billed minus the $90.00 adjustment is $160.00 allowed, and $160.00 minus $64.00 of patient share is the $96.00 plan payment. A mapping that keeps every printed column as its own adjudication entry lets a reader check that arithmetic from the resource alone.

Required ExplanationOfBenefit elements that paper EOBs lack

The FHIR ExplanationOfBenefit resource requires several elements that a printed EOB never states outright: status, type, use, created, outcome and an insurance entry with focal and coverage. When the page does not say, the mapping has to supply a value from context and record that the value was inferred.

The R4 page lists the required top-level elements. status takes one of active, cancelled, draft or entered-in-error. type is a claim type code such as professional or institutional. use takes claim, preauthorization or predetermination. outcome takes queued, complete, error or partial. patient, created, insurer and provider are each required once, and insurance must appear at least once with its focal flag and a coverage reference.

Most of these can be filled honestly from what an EOB is. A printed EOB describes a processed claim, so use is claim and outcome is usually complete. A record you create from a page you received is active. The FHIR claim type codes are institutional, oral, pharmacy, professional and vision, and the EOB's layout and the codes on its lines usually show which one applies.

Other required elements need resources you may not have. insurer and provider are references, so the payer and the provider need Organization or Practitioner resources, even minimal ones built from the printed name and address. insurance.coverage points to a Coverage resource, which is where the member ID belongs. created is the date the resource was created; the printed EOB date is a reasonable value, but write down which rule you used.

Three mistakes come up often:

  • Inventing an outcome. If the page shows a line as pending or the claim as partly processed, partial or queued is more honest than complete.
  • Dropping the inference. A value the page did not print should be traceable as inferred, for example through a Provenance resource or your own audit record, so a reader can tell what came from the page.
  • Faking payment detail. The R4 page says payment details other than the date should be left out when the payee is the provider. Do not fill payment from a guess.

Low-confidence fields are a separate problem. If the reader of the page was unsure of an amount, a person should confirm it before it becomes an adjudication entry, because a FHIR resource looks authoritative to everyone downstream.

Which ExplanationOfBenefit profiles should I validate against?

Validate first against the base FHIR R4 ExplanationOfBenefit definition, then against the implementation guide your receiver names. In the United States, the HL7 CARIN Blue Button guide covers payer-to-consumer claims data and defines separate ExplanationOfBenefit profiles for professional, institutional, oral and pharmacy claims.

The base specification only checks shape: required elements, cardinality and the bound value sets. It allows almost any code in adjudication.category, because that binding is an example. A profile narrows those choices. The CARIN Blue Button implementation guide is published as version 2.2.0, STU 2, on FHIR R4, and is the current published version. Its profiles include Inpatient Institutional, Outpatient Institutional, Professional NonClinician, Oral and Pharmacy.

Pick the profile that matches the paper. The C4BB ExplanationOfBenefit Professional NonClinician profile says it is for EOBs based on claims from physicians, suppliers and other non-institutional providers, and that its data is based on the CMS-1500 professional claim form. The guide's Inpatient Institutional and Outpatient Institutional profiles are separate, so check which one your receiver expects for a hospital EOB. The profile also says it has requirements for financial data, so a resource missing the adjudication amounts a printed EOB carries will fail it.

Expect profile validation to be strict in ways a paper source cannot always meet. A profile may require identifiers, codes or slices that the printed page does not show. When that happens, the choice is between leaving the resource valid against the base specification only, or asking the receiver what it accepts. Do not fill a required element with a placeholder that looks like real data.

If the same pipeline also produces lab resources, the same validate-base-then-profile habit applies, as the guide to FHIR DiagnosticReport and Observation for lab data shows. If your receiver turns out not to accept FHIR at all, the comparison of HL7 v2 vs FHIR for extracted document data covers the older message format.

All posts in APIs, FHIR and Integration