Tool note
Epic: FHIR Version Fragmentation, per Operation
The same resource can support read at one FHIR version and create at another, so plan per operation rather than per resource.
“Does Epic support Condition?” is a question with no useful answer. The resource is published; that tells you almost nothing about whether the thing you need to do with it is available to you.
The unit of support is not the resource. It is the resource, the operation and the FHIR version together, and sometimes a specifically named API variant on top of that.
Why this exists
The failure mode is quiet and expensive. You check a support index, see your resource listed, choose a version for the app, and estimate from that. In week three the create you need turns out not to exist at the version your reads use, and now you are choosing between a mapping layer, a second version in the client, and telling the client a feature is cut.
Two worked examples from Epic’s own published index show the shape. Condition (Problems) has Read, Search and Create on R4, Create on STU3, and Read and Search on DSTU2, plus a CDS Hooks variant on R4. Immunization is stranger: base Read and Search are STU3 and DSTU2, while R4 arrives as separately named Immunization.Read (Patient Chart) and Immunization.Search (Patient Chart) APIs.
Here is the consequence people miss. Two versions of one concept are two data shapes. A DSTU2 Condition and an R4 Condition are not the same JSON, so an app that reads one and writes the other owns a mapping, and a test for that mapping, for as long as the feature lives. That cost belongs in the estimate rather than in week three.
How to use it
Build the matrix before the estimate goes out. One row per operation you actually need, with the published API name copied exactly, the versions it exists at, the scope, whether it matches your app’s primary version, and a decision.
- Every row gets exactly one decision:
build,map,add version,cut, orinvestigate. A row with no decision is an assumption, and assumptions are what the matrix is for. - Price
investigaterows as time-boxed investigation instead of folding them into the build number. That is the honest way to charge for not knowing yet. - Write the date you checked the index on the sheet. A matrix with no date is a rumor, because published support moves.
- Where an operation is published under a specific name, copy the name character for character. Registration and scopes attach to the published name, not to the resource concept, and a near-miss name fails at the token rather than at the parser — which is a much less obvious error to read.
- Treat base URL, client identifier and organization identifier as configuration held in one place. They do change: a sandbox notice dated August 31, 2026 reverted the sandbox organization identifier to
0from529and told integrators who had switched to revert their identifiers. - Put the
cutrows in the scope document, so the cut is visible to the client rather than quietly absorbed by you.
Where it goes wrong
The matrix is a planning tool, not a compatibility guarantee. A published index tells you what exists in general. A specific site’s configuration, licensing and version decide what you actually get, so confirm per site and write that confirmation date next to the row.
Do not copy version answers out of anybody’s worksheet, including this one, into a live plan. Look it up yourself the week you commit to it.
If your app reads one resource one way, the matrix is a single row and the ceremony is waste. Scale the artifact to the surface you are touching.
And be suspicious of your own willingness to add a version. Supporting two means every change ships twice, is tested twice, and breaks in two ways. Cutting the feature is sometimes the better engineering decision, and part of what the matrix is for is making that trade visible early enough that you can still take it.
Copy and Clear become available when the worksheet is ready.
FHIR OPERATION x VERSION MATRIX
App: Site:
Checked against the published support index on:
Primary version chosen for this app:
A matrix with no checked-on date is a rumor. Re-check before go-live.
ONE ROW PER OPERATION YOU ACTUALLY NEED
resource | operation | published API name (exact) | version(s) | scope | matches primary? | decision
Condition (Problems) | Read | | R4, DSTU2 | <> | <> | <>
Condition (Problems) | Search | | R4, DSTU2 | <> | <> | <>
Condition (Problems) | Create | | R4, STU3 | <> | <> | <>
Immunization | Read | Immunization.Read (Patient Chart) | R4 | <> | <> | <>
Immunization | Read | base resource as published | STU3, DSTU2| <> | <> | <>
| | <> | <> | <> | <> | <>
The rows above show the shape of the problem - the same concept carrying
different operations at different versions, and an R4 operation published under
its own name. They are not a substitute for looking your own operations up in
the index on the day you estimate.
DECISION VALUES - every row gets exactly one
build exists at my primary version; nothing special to do
map I must call another version; I own the shape mapping and its test
add version I will support a second version in the client
cut the feature does not ship, and the client is told in writing
investigate I do not know yet; priced as investigation, not as build
FOR EVERY "map" ROW, ANSWER
FOR EVERY "add version" ROW, ANSWER
NAMED API VARIANTS
Some operations are published as separately named APIs rather than as the plain
resource. Registration and scopes attach to the name.
CONFIGURATION THAT WILL MOVE UNDER YOU
dated August 31, 2026 reverted the sandbox organization identifier to 0
from 529 and asked integrators who had switched to revert their OID
system identifiers.