General guidance
Profiles
FHIR is based on "Resources" which are the common building blocks for all exchanges. A resource is an instance level representation of some kind of healthcare entity.
The FHIR specification describes a set of base resources, frameworks and APIs that are used in many different contexts within healthcare. The FHIR specification is a "platform specification" - it creates a common platform, or foundation, on which a variety of different solutions are implemented. As a consequence, this specification usually requires further adaptation to particular contexts of use. For this reason FHIR includes the possibility to create profiles. A profile is a structure definition with constraints on the resource it represents, i.e. a profile is a description of an implementation of a resource in a specific context.
"Must support" property
The general approach of customizing FHIR resources in this guide is to mark elements that are used within a resource with the FHIR must support flag rather than excluding elements by cardinality, i.e. 0..0, to facilitate interoperability.
The must support flag indicates that the element is expected in some use cases, and a missing flag that the element is never used. Note that this does not apply to meta data, for example the id and versionId elements of a resource.
Constraining elements
Elements can be profiled to be constrained in different ways. The following section describes the methods used in this guide to constrain elements from the base resources. This is both to clarify the data structure that will be returned from search operations as well as to express the validation rules that apply when submitting data. Each profile defines the constraints relevant for its elements, which are also summarized on each page in this guide in a human readable format.
Note that another type of constraint is binding an element to a value set. See section about code systems and value sets for more information.
Cardinality
FHIR generally supports a cardinality of 'zero to many' in a majority of the elements. This is in order to have a flexible structure to cater for different scenarios.
In the profiles, the cardinalities of the used elements (marked with "must support") is narrowed to support the use cases in which the element is used.
Invariants
An element can have constraints, also called "invariants", that specify rules which the element has to follow. In this guide they are found by hovering over an element in a resource tree, under the title "Constraints". If a constraint is not followed, the server might return a warning or an error. The constraints can come from the base specification of the resource or from the profiles. Those that are defined in this guide are prefixed with "hvo". The constraints for each resource are listed on the corresponding pages.
Fixed values
Another way in which an element might be constrained is if it has a fixed value. This means that the fixed value SHALL be used when submitting data for that element and SHALL be used when returning data for that element. This applies if the element has a label of "fixed value" next to it. Hovering on the element will show the fixed value in question under the same label.
Slices
Some profiles might contain different alternatives for certain elements. It can be either mandatory or not to choose one of the alternatives. These alternatives are called slices in FHIR. Slices of an element are always distinguished by a discriminator, for example a value of a sub element, and have names that represent the alternatives. They might be used to express different constraints of the element, for example different cardinalities, invariants, value set bindings, e.t.c., depending on this discriminator. It is not expressed in the body of an operation which slice is being adapted - it is understood from the discriminator.
An example of slicing is found in the Organization - HVOOrganization profile, which for this example defines different slices for the identifier element. They are determined by the system sub element. One slice profiles the identifier element if the system is "urn:oid:1.2.752.29.4.19", named "hsaid", and the other if the system is "urn:oid:2.5.4.97", named "organizationIdentifier" (note the "fixed value" label (see the section above) by the system elements). The two slices can then define different invariants (see the section above) on the value element, in order to make sure that the value is entered correctly depending on the system. As previously stated, it is not expressed in the JSON body of a request which slice has been chosen, it is solely inferred by which value is provided of the identifier.system element in this case.
Identifiers
All resources have a logical identifier in the id element. The logical identifier is assigned by the server and is unique on that server. A resource can be fetched by referring to its logical ID in the form [base]/[resource-type]/[id] e.g. [base]/Organization/123 where 123 is the logical ID. A logical ID SHALL never change after it has been assigned to a resource. Se more information about the ID element in the section references.
Resources can also have a business identifier in the identifier element. A business identifier is a well known inter system identifier. Business identifiers are always defined by a system ID, for example an OID or a URI. In FHIR, this is the ID that goes in the Identifier.system element. The value of the identifier goes in the Identifier.value element. When performing search queries using a business identifier, the identifier system should always be provided. This is done in the following format: GET [base]/[resource-type]?identifier=[system]|[value], e.g. [base]/[Organization]?identifier=urn:oid:2.5.4.97|5560269986 where the system ID is urn:oid:2.5.4.97 and the value of the identifier is 5560269986.
Resource version
All persistent resources SHALL be conceptually versioned and the version information SHALL be supplied in the meta element.
"meta": { "versionId": "b2e33b8a-c5f1-430e-888e-ac5130513980" }
A previous version of a resource SHOULD be found by requesting it through the _history operation [base]/[resource-type]/[id]/_history/[vid], e.g. [base]/Organization/81a98656-4cec-442d-a82a-6a0476e0f3a0/_history/2, will fetch the version with versionId b2e33b8a-c5f1-430e-888e-ac5130513980 of the Organization with logical id 81a98656-4cec-442d-a82a-6a0476e0f3a0.
References
A reference to another resource in the same server is usually done as a literal reference, i.e. by an URL pointing at the resource. The referenced resource can then be fetched via the URL in a separate request. A literal reference can be either absolute or relative. An absolute reference is a complete URL, i.e. https://domain.org/fhir/Patient/123. A relative reference omits the service base URL, i.e. Patient/123.
In some cases it is not possible to reference another resource because the other resource has no identifier. One reason for this is if the resource is not persistent. Another case is when the resource exists only in the context of the referencer, e.g. an Organizational Unit includes a Business resource with no identifier. References to inline resources is in FHIR called contained resources and such references starts with a #, e.g. #p1. If the inline resource has to reference its containing resource, it is done using a single #. See FHIR contained resources for more information.
The snippet below includes both a literal relative reference and a reference from a contained resource to its containing resource.
{
"resourceType": "Organization",
"contained": [
{
"resourceType": "HealthcareService",
"id": "p1",
"providedBy":
{
"reference": "#"
}
}
],
"partOf": {
"reference": "Organization/aa9e5f2b-a906-4312-9d13-61fd46d63f58"
}
}
Extensions
The HL7 FHIR specification covers the most common resource types and the most common elements within those resources for the healthcare industry. Concepts that are of less common use can be added to the generic resources by adding so called FHIR extensions. See Extensions for more information and a list of all extensions defined in this guide.
Code systems and value sets
The profiles in this guide are to a large extent based on coded values published as terminologies, later referred to as code systems and value sets. Code systems and value sets are used within elements of the type code. Coded values are used in many FHIR resources to structure the information and make it system readable. The content of code systems and value sets define a set of values in a specific context. The expression code is commonly also called concept and is a structured and often standardized way of expressing a value.
A code system or value set can represent codes from a wellknown terminology e.g. Snomed CT or locally defined codes.
The picture below shows how the binding to code systems or value sets can be seen in a FHIR profile elements. In this case, the profile HVOBusiness has an element with a binding (1) to the value set hvo-business-category (2) which defines all valid codes for the element.
Value sets were the basepath of the URI starts with http://electronichealth.se or http://ehalsomyndigheten.se are defined by the Swedish eHealth Agency and can be fetched from the endpoint [base]/ValueSet. Value sets and code systems defined by other organisations are usually not republished by the Swedish eHealth Agency. The identity of a value set or code system can take many forms, e.g. OID, URI etc. An URI identity may in some cases be used as an URL as well, and make it possible to look up and view the concepts by a browser.
CodeableConcept, Coding and code
The way FHIR usually uses codes in resources is by defining a CodableConcept. One single concept can be described in CodableConcept by specifing one or more Codings (with a codes and potentially a textual description). In some cases the use of codes in the resource is very strict, e.g. in the "status" element that is available in many resources. In those cases a plain code is used.
Resource types and relations
The figure below shows how the terminology resources relate to each other.
Code System
A code system is a set of concepts where each concept has a unique code and a display name and possibly a definition of the concept. Each code system also has a globally unique identifier, sometimes in the form of an URI or OID. When exchanging a coded element in FHIR, the elements used for this information is Coding.code, Coding.display and Coding.system respectively.
No code systems are published in this guide but each value set refers to the code system of each code in the value set.
Value Set
A value set is a subset of codes from one or more code systems. A code is understood in a value set only in combination with what code system it is from, hence this information always has to be present when exchanging coded values. In actual implementations you can often see value sets and code systems being mixed up. While FHIR elements are bound to value sets to show which subset of codes are valid for those elements, it is always the code system that is specified in the Coding.system element. If you can not read which code system the code comes from, you do not know what code it is - in theory, one code can by chance be the same in multiple code systems.
FHIR and REST
General considerations
FHIR® resources are exchanged using the RESTful paradigm. Each "resource type" has a selection of the same set of interactions defined that can be used to manage the resources in a highly granular fashion. Transactions are performed on the server resource using an HTTP request/response.
Recommended reading, in complement with this implementation guide, is the FHIR RESTful API.
FHIR Version
This guide uses the R5 version of FHIR.
Resource formats
By default FHIR has support for exchanging data both in JSON and XML format. See HL7 FHIR Resource format
Notation
Throughout this guide the following notation is used to define interactions. It follows the same principles as the notation used by HL7 Style Guide.
VERB [base]/[type]/[id]{?name_1=[value]}
- VERB The HTTP method, i.e. GET, POST, PUT.
- [xyz] Mandatory parameters are surrounded by square brackets.
- {xyz} Optional content is surrounded by curly brackets.
General parameter types:
- [base] The Service Base URL, i.e.
http{s}://[domain]{/[path]}. - [type] Type of resource, e.g. Location, Organization e.t.c..
- [id] Logical ID of an instance of a resource.
- [vid] Version ID of an instance of a resource.
- [parameters] Placeholder for all parameters as defined for the specific interaction.
To describe the allowed behavior of a search parameter, the following notations are used:
- multipleAnd The parameter may repeat in order to specify multiple values that must all be true ("and"), i.e.
type=X&type=Y - multipleOr The parameter may have multiple values (separated by comma) where at least one must be true ("or"), i.e.
type=X,Y
Basepath
All examples in this implementation guide refers to a [base] in the start of an URI/URL. Base is an abbreviation of Service Base URL.
For more information about the basepath see HL7 Service Base URL.
URIs vs URLs and encoding or URLs
FHIR use URIs (Uniform Resource Identifier) and URLs (Uniform Resource Locator) frequently as a way to identify things and point at where things can be found. For example a code in a value set is bound to the code system where the code is defined. The code system is identified by an URI, e.g. "http://unitsofmeasure.org". An other example are FHIR profiles and extensions who has a canonical identifier in the form of an URI, e.g. "http://electronichealth.se/fhir/StructureDefinition/HVOBusiness".
An URL is an URI that acts as an address to something. In the latter example above the element is named url to reflect the idea that the specification should be available on the same address as it's identification. NB! This is not the case yet for profiles, extensions and value sets defined in this guide.
An URI is based on US-ASCII and characters like :/?= has a special meaning. It is important to encode an URI correctly to avoid technical issues. An example is when performing a search when the URL is GET [base]/Organization?identifier=urn:oid:2.5.4.97|1234. This may or may not work in a practical scenario but to avoid issues the URL should be encoded: GET [base]/Organization?identifier%3Durn%3Aoid%3A2.5.4.97%7C1234.
More information about URIs and URLs can be found at http://hl7.org/fhir/R5/http.html#general, http://hl7.org/fhir/R5/datatypes.html and https://www.rfc-editor.org/rfc/rfc3986.
CRUD operations
Create
A create interaction is performed using an HTTP POST with the resource in the body of the request.
POST [base]/[type]
The server SHALL create a new instance of the resource with a version ID if the content meets the validation and business rules. If the body contains an id element, the server SHALL ignore it and assign a new logical ID.
If the resource was sucessfully created the server SHALL return HTTP status 201 and a Location header which contains the new logical ID and version ID of the created resource. If there was an error creating the resource, due to for example body content not being compliant to the resource profile, a HTTP status of 400 or higher SHALL be returned.
Create is not supported for all resources. See the section for each profile to see supported actions.
Read
A read interaction accesses the current contents of one or several resource(s). The interaction is performed by an HTTP GET command. The operation SHALL return one single resource with the provided logical ID if it exists, otherwise a HTTP status 404, 410 or similar is returned if the resource does not exist or is inaccessible.
GET [base]/[type]/[id]
An example of a read request of an Organization with logical ID 54ff7817-4e4e-4215-9b90-b29a8c0c3143:
GET [base]/Organization/54ff7817-4e4e-4215-9b90-b29a8c0c3143
Resources which are available as contained resources (see References for more information) (e.g. HealthcareService - HVOBusiness) cannot be fetched by their logical ID.
Update
An update interaction is performed using an HTTP PUT with the resource in the body of the request. The body resource SHALL have an id element that has an identical value to the id in the URL.
PUT [base]/[type]/[id]
The server SHALL create a new instance of the resource with a version ID if the content meets the validation and business rules. Update action is not supported for all resources. See the section for each profile to see supported actions.
If the resource was sucessfully updated the server SHALL return HTTP status 200 and a Location header which contains the Logical ID and version ID of the updated resource. If there was an error creating the resource, due to for example body content not being compliant to the resource profile, a HTTP status of 400 or higher SHALL be returned.
Delete
This guide does not support delete operations. Instead the resource which is no longer valid or faulty should be updated to reflects this, for example through changing the status or setting an end date. How this is done is described on each profile page.
Search
A search for information is typically performed by the HTTP GET method followed by the domain adress, the resource and optional parameters. A search is defined by using a question mark in the url.
A successful search SHALL return HTTP status 200 OK and a Bundle with type set to "searchset" and containing the result of the search as a collection of one or more resources.
GET [base]/[type]{?[param=value]{&[param=value]...}}
Each parameter is entered after the question mark as a series of name=value pairs separated by an ampersand.
Examples:
- To search for an organization with the logical ID 123.
GET http://acme.org/fhir/Organization?_id=123 - To search for all contracts where the description contains a specific string.
GET http://acme.org/fhir/Contract?term-text:contains=[Description]
When the logical ID is known, as in the first example above, a read can be performed instead.
GET [base]/[type]/[logical ID]
Example:
GET http://acme.org/fhir/Organization/123
There are many search parameters and search result parameters described in the FHIR specification, both in general and per resource. The supported subset of those parameters are specified per profile in this implementation guide.
For more information about searching in FHIR see HL7 FHIR Search and HL7 FHIR HTTP Search. See URIs and URLs for information about encoding of search URLs.
Paging
This guide contains search queries where the response is recommended to be paginated in order to minimize the load on the server. When such a query is performed, the response Bundle SHALL contain the first page of results as well as URLs which can be used to request additional pages. Every page of results will have URLs for requesting additional pages.
The _count parameter SHALL be used to request the number of posts that should be returned. The _offset parameter SHALL be used to request which "page" should be returned - i.e. how many posts the server should skip before returning the number of posts supplied by the _count parameter. The recommended max number and default number of _count can differ between queries and is documented on each paginated query in this guide. The max number of _offset is relative to the number of posts that the search results in and the value for _count. The default number of _offset SHALL always be 0.
Below is an example of how a response might look when requesting the third page of a paginated response when the _count is set to 10.
{
"resourceType": "Bundle",
"type": "searchset",
"total": 1234,
"link": [
{
"relation": "self",
"url": "http://example.org/Patient?name=peter&_count=10&_offset=20"
},
{
"relation": "first",
"url": "http://example.org/Patient?name=peter&_count=10&_offset=0"
},
{
"relation": "previous",
"url": "http://example.org/Patient?name=peter&_count=10&_offset=10"
},
{
"relation": "next",
"url": "http://example.org/Patient?name=peter&_count=10&_offset=30"
},
{
"relation": "last",
"url": "http://example.org/Patient?name=peter&_count=10&_offset=60"
}
],
//then the search results...
}
The link with a relation of "self" represents the current page. In order to go to the next page, the URL of the link with a relation of "next" can be used, e.t.c.
Special operations
OperationDefinition resources are used to define special operations where the search parameters defined for a resource does not cover a specific use case.
Operations can execute on three different levels:
- system level (
POST or GET [base]/[operation]), - resource type level (
POST or GET [base]/[resource]/[operation]) or - instance level (
POST or GET [base]/[resource]/[id]/[operation]).
It is specified on each OperationDefinition on what level and what, if any, resource it can be used on. It is also specified on each profile in the guide which special operations are available for that profile.
Error handling
A request that fails is typically returning an OperationOutcome.
Returned information
This impacts on error management as the information returned describing the error depends on the tier where the error occured.
First thing to check is the HTTP status, e.g.
HTTP/1.0 503 Service Unavailable. The HTTP status returned is the most importent information about the outcome of the request. Anything in the 200 range indicates a success, and anything else a failure.Next thing is to check is what kind of data the HTTP body contains by looking at the content type header field.
Content-Type: "text/html"would for example indicate that an error occured at the transport layer beacuse a FHIR response SHALL be tagged asapplication/fhir, e.g.Content-Type: "application/fhir+json; charset=UTF-8". A non FHIR response should be treated as a system error.The third thing to check is what type of FHIR resource the response body contains. This would in most cases be either nothing, an OperationOutcome, a Bundle or the requested resource. An error will however always result in an OperationOutcome independent of the requested outcome. The last thing when it comes to errors is to check what the OperationOutcome says about the error. How to interpret the OperationOutcome is covered in the next section.
The OperationOutcome resource
OperationOutcome is a very versatile resource that can handle information in many ways. This can make it a daunting task to build a generic error handling mechanism on the receiving end. Below is a summary of recommended principles when transmitting data as an OperationOutcome to make this task a little easier. It is important to understand that the FHIR component relies on backend systems and run on top of a routing layer. The principles can therefore not be guaranteed.
In the text below, a successful request is one with an HTTP status in the 200 range. A failed request is one with an HTTP status in the 400 or 500 range.
issue.severity SHALL be set to one of the 4 IssueSeverity codes. In case of a failed request issues that are the cause of the failure SHALL be tagged as "error" or "fatal". Issues tagged as "information" or "warning" are not the cause of the failure.
issue.code SHALL be set to one of the IssueType codes. The code SHOULD give a good indication of the issue type in most cases, but it is not guaranteed.
issue.details SHALL include an error code and a error message.
details.coding.code SHALL contain a code that defines what the issue is about. A code SHOULD be in the format n-nn-nnn, for example: 2-26-104.
details.coding.display SHALL contain the display text from the code system. The display text MAY contain parameters (dynamic parts) that are populated when the issue occurs.
diagnostics MAY be populated to facilitate in depth error investigations.
Transactions and Bundles
Bundles can be used for handling multiple resources within one transaction. In this scenario the transaction SHALL return a successful result only if all actions in the transaction are accepted by the server. Otherwise the transaction SHALL be rejected.
A failed transaction SHALL result in a HTTP status in the 400 or 500 range and in one single OperationOutcome instead of a Bundle. The element OperationOutcome.issue.expression SHALL contain information about which resource and element in the request Bundle that raised the issue. See FHIR Transaction processing rules.
Exceptions
Routing error
Errors that occur at routing level and never reaches the FHIR component will result in a non FHIR response.
It may look like this.
HTTP/1.0 503 Service Unavailable
Connection: close
Content-Type: text/html
<html>
<head>
</head>
<body>
<div>
<h1>Application is not available</h1>
<p>The application is currently not serving requests at this endpoint. It may not have been started or is still starting.</p>
</body>
</html>
FHIR parsing error
Servers may be based on FHIR libraries with built in error handling for low level communication, such as the HAPI FHIR library. Errors caught by HAPI will result in an OperationOutcome that follows another structure than the one described above.
It may look like this.
HTTP/1.1 400 Bad Request
Content-Type: application/fhir+json; charset=UTF-8
{
"resourceType": "OperationOutcome",
"issue": [ {
"severity": "error",
"code": "processing",
"diagnostics": "Multiple values detected for non-repeatable parameter 'code'. This server is not configured to allow multiple (AND/OR) values for this param."
} ]
}