CapabilityStatements¶
A profile tells you what a resource looks like. It does not tell you whether you can ask the server for one. A CapabilityStatement is the artifact that answers the second question: which resource types this endpoint serves, which operations it honours on each, which search parameters a query may rely on, and which profile the instances it returns are served against.
That is the first thing an integrator needs and the last thing a profile can tell them. Reading every StructureDefinition in this specification will not reveal which types an application can reach, because that is not what a StructureDefinition is for.
The one this guide publishes¶
| Statement | The question it answers |
|---|---|
| Server | What may an application do against a Nexus EMR FHIR endpoint? Resource types, the interactions offered on each, and the profiles they are served against. |
It is kind = requirements. That word matters: it states what a conformant endpoint must
offer. It is not a description of any particular deployment, and it is not what a running server
returns from /metadata -- an instance publishes its own statement, and may legitimately offer
more than this document requires or less of an optional interaction than it declares.
A second statement was published from 1.17.0 to 1.25.1 and has been withdrawn. It declared the
vocabulary a Subscription.criteria could draw on, one entry per subscribable type. The content was
sound; the carrier was not. A CapabilityStatement expresses a criteria vocabulary only by writing it
into rest.resource.searchParam, and that element means "this endpoint serves a REST search on this
type with these parameters" -- a different and stronger claim than "a subscription criteria may name
these parameters", and one that was not true. The vocabulary, and the constraints that go with it,
now live in Subscriptions, which also states plainly that this API does not
offer the Subscription type to applications at all.
A canonical URL is an identifier, not an address¶
Each statement has a canonical URL: https://fhir.apps.health/CapabilityStatement/nexus-emr-server.
That string is the artifact's name. It is how a Subscription statement says which server
statement it instantiates, how a validator resolves the artifact out of a package, and how two
systems agree they mean the same document.
It is not a link. Nothing is served at it, in development or in production. The website is somewhere else entirely, and the page you read the artifact on is the one linked from the table above. A canonical pasted into a browser resolves nowhere -- which is the correct behaviour, not a gap waiting to be filled: an identifier that is also an address is an identifier that breaks when the hosting moves. Canonical URLs covers the base and the rule in full.
So: cite the canonical, link the page. A document that needs to name the artifact writes the
canonical in backticks. A document that wants the reader to go and read it links the reference
page with a relative .md target.
Reading the resource table¶
Each statement's page carries one row per resource type. A linked type name has further notes below the table; the rest are fully described by their row.
Interactions¶
An interaction is one thing an application may do against that type. In R4:
| Interaction | What it means |
|---|---|
read |
Fetch one resource by its id: GET [base]/Patient/123 |
search-type |
Query the type and get a Bundle back: GET [base]/Patient?... |
create |
Post a new resource of that type |
update |
Replace an existing resource of that type |
delete |
Remove one |
Exposure is not all-or-nothing, and the interaction list is the only place the answer is stated.
Three shapes recur on the server statement: read-only, everything-but-delete, and full. The middle
one is the one to notice -- for several types, withdrawal is a status change
(entered-in-error, cancelled, revoked) rather than a delete, because destroying the record
would be data loss rather than a workflow step. Where an entry is narrower than you would guess,
its notes say why.
The server statement's type list and its interactions are derived from the exposure each profile declares for itself, rather than maintained by hand alongside them. A narrowed exposure therefore cannot leave a stale entry behind here.
Search parameters¶
A searchParam entry declares that a query naming that parameter is part of the contract: the
server is expected to honour it and filter on it. A declared _include says the server can return
referenced resources in the same Bundle, so a client need not make a second round trip.
What a declared parameter does not promise is anything about the parameters that are absent. A
CapabilityStatement declares; it does not exhaustively deny. A type listed with no searchParam
block is not a claim that the type supports no searches -- it is a claim that this guide is not
yet standing behind any.
That distinction is doing real work here, because the general search surface varies by backing store and this guide will not publish a list it has not measured against each one. Search parameters are therefore declared on a handful of types and not on the rest, and beyond those this guide stands behind no search surface at all.
Two failure modes make this worth caring about rather than filing away. A search naming an
unsupported parameter does not error: it returns a bundle computed without the filter, or an
empty one, and the caller cannot tell "nothing matched" from "the server ignored what you asked".
And a modifier the store silently drops is worse than a missing one -- owner:missing=true against
a server that ignores :missing answers with every task, which looks exactly like a match.
Declared is not measured¶
Read the per-parameter notes on the server statement, because they carry a distinction the FHIR resource has no field for: some declared parameters have been measured against a running store and some have not, and every entry says which it is.
This is deliberate rather than sloppy. Under kind = requirements, a parameter a consuming surface
depends on is a requirement whether or not a store has yet been observed to serve it, and telling
an implementer "this is required and unverified" is worth more than telling them nothing -- but
only for as long as the two are never allowed to blur. Hence the per-parameter labelling.
A measured entry rests on a conformance request that asserts what the filter must exclude, not merely that a request succeeded: a parameter the store dropped would answer with everything, which a request asserting only "some rows came back" would happily accept. An unmeasured entry is a requirement on a conformant server and a risk on a particular one, and a client depending on it should verify the server honours it rather than reading an empty result as an empty set.
The labelling is per parameter and not per type for a concrete reason, and :missing is the case
that shows why. It was measured absent on 2026-08-25 -- patient:missing returned the same
unfiltered set for true and false -- and measured present on 2026-09-08, directly against the
store image, where owner:missing=true returned only the unowned task, owner:missing=false only
the owned one, and an unfiltered control returned both. The store's source agrees with the second
result.
Two measurements of the same estate disagree, so the honest state is neither "supported" nor "unsupported" but unsettled, and this specification declares nothing on an unsettled question. What has not been measured is the whole chain at once, which is what would settle it. Until then the guidance elsewhere -- filter for unassigned work on the client -- stands, because the cost of trusting a dropped modifier is that every task reads as a match, silently.
Profiled is not exposed¶
This is the most misread thing about the artifact, so it is worth stating flatly.
Modelling a resource says the estate contains it. Exposing it says an application may reach it. The two are decided separately. This guide profiles more types than the server statement lists, and the ones it models without listing are absent by decision, not by oversight. The absence is the statement: an implementer meeting one of those types in a payload is meeting data this guide describes but does not offer as an API surface, and no SMART scope naming it is granted.
To find them, compare the profile list on the artifacts index against the resource table on the server statement. The reason each one is held back -- and what would decide it differently -- is recorded in that statement's FSH source, linked from its own page.
The reasons are not uniform, which is why there is no single rule to apply instead. Some types are not ordinary REST surfaces at all. Some are access logs, where exposure is a decision taken per consumer rather than inherited from the profile existing. Some ship with the software rather than travelling over the API. And several are simply closed to applications pending an exposure decision, each of which needs a consumer that names the type and the interactions it needs.
See Also¶
- Canonical URLs -- the base every artifact is published on, and why the canonical is not somewhere to point a browser
- Nexus EMR Identifiers and References -- canonical URL structure
- Artifacts -- the full index of everything this specification defines