PATIENT ADMINISTRTAION (PA) Workgroup Development Draft

2.1.0 RESTful API

Each resource type has the same set of interactions defined that can be used to manage the resources in a highly granular fashion. Applications claiming conformance to this framework claim to be conformant to "RESTful FHIR".

Note that in this RESTful framework, transactions are performed directly on the server resource using an HTTP request/response. The API does not directly address authentication, authorization, and audit collection - for further information, see the Security Page.

The API describes the FHIR resources as a set of operations (known as "interactions") on resources where individual resource instances are managed in collections by their type. Servers can choose which of these interactions are made available and which resource types they support. Servers SHALL provide a conformance statement that specifies which interactions and resources are supported.

The following logical interactions are defined:

Instance Level Interactions
readRead the current state of the resource
vreadRead the state of a specific version of the resource
updateUpdate an existing resource by its id (or create it if it is new)
deleteDelete a resource
historyRetrieve the update history for a particular resource
Type Level Interactions
createCreate a new resource with a server assigned id
searchSearch the resource type based on some filter criteria
historyRetrieve the update history for a particular resource type
Whole System Interactions
conformanceGet a conformance statement for the system
transactionUpdate, create or delete a set of resources as a single transaction
historyRetrieve the update history for all resources
searchSearch across all resource types based on some filter criteria

In addition to these interactions, there is an operations framework, which include endpoints for validation, messaging and Documents.

Style Guide

The interactions on this page are defined like this:

  VERB [base]/[type]/[id] {?_format=[mime-type]}
  • The first word is the HTTP verb used for the operation
  • Content surrounded by [] is mandatory, and will be replaced the string literal identified. Possible insertion values:
  • Content surrounded by {} is optional

Implementations constructing URLs using these patterns SHOULD conform to RFC 3986 Section 6 Appendix A which requires percent-encoding for a number of characters that occasionally appear in the URLs (mainly in search parameters).

2.1.0.1 Service Root URL

The Service Root URL is the address where all of the resources defined by this interface are found. The Service Root URL takes the form of

http(s)://server{/path}

The path portion is optional, and does not include a trailing slash. Each resource type defined in this specification has a manager (or "entity set") that lives at the address "/[type]" where the "type" is the name of the resource type. For instance, the resource manager for the type "Patient" will live at:

https://server/path/Patient

All the logical interactions are defined relative to the service root URL. This means that if the address of any one FHIR resource on a system is known, the address of other resources may be determined.

Note: All URLs (and ids that form part of the URL) defined by this specification are case sensitive.

Note that a server may use a path of the form "http://server/...[xx]..." where the [xx] is some variable portion that identifies a particular instantiation of the FHIR API. Typically, the variable id identifies a patient or a user, and the underlying information is completely compartmented by the logical identity associated with [xx]. In this case, the FHIR API presents a patient or user centric view of a record, where authentication/authorization is explicitly granted to the URL, on the grounds that some identifiable user is associated with the logical identity. It is not necessary to explicitly embed the patient id in the URL - implementations can associate an FHIR end-point with a particular patient or provider by using an OAuth login. See Compartments for the logical underpinning.

Identity

Systems often need to compare two URLs to determine whether they refer to the same URL or not. For the purposes of this specification, the following rules apply:

  • The query part of the URL (anything after '?' is ignored
  • The comparison of the document portion of the URL (i.e. not the server/port) is case sensitive
  • http: and https: are exchangeable and refer to the same object
  • If a port is specified, then the ports must be identical or the objects are different (to the prevalence of port mapping and/or interface engines running on different ports). Ports should only be explicit when they have explicit meaning to the server

For example: http://myserver,com/patient/1 and https://myserver.com/patient/1 are the same, while http://myserver.com:80/patient/1 is distinct from either of the above.

Note: the identity comparison for protocols other than http/https is undefined.

2.1.0.2 Resource Metadata and Versioning

Each resource has an associated set of resource metadata elements. These map to the http request and response using the following fields:

Metadata ItemWhere found in HTTP
Logical Id (.id)The Id is represented explicitly in the URL
Version Id (.meta.versionId)The Version Id is represented in the ETag header. It SHOULD also be returned as a full canonical URL in the Content-Location header (see vread below)
Last modified (.meta.lastUpdated)HTTP Last-Modified header

Note that the Version Id is considered a "weak" ETag and ETag headers should be prefixed with "W/" and enclosed in quotes, for example:

ETag: W/"3141"

2.1.0.3 Security

Using HTTPS is optional, but all production exchange of healthcare data SHOULD use SSL and additional security as appropriate. See HTTP Security for further information.

The choice of whether to return 403 or 404 depends upon the specific situation and specific local policies, regulations, and laws. The decision of which error to use will include consideration of whether disclosure of the existence of relevant records is considered an acceptable disclosure of PHI (Personal Health Information) or a prohibited disclosure of PHI.

Note: to support browser-based client applications, recommend that servers SHOULD implement cross-origin resource sharing for the operations documented here.

2.1.0.4 HTTP Status Codes

This specification makes rules about the use of specific HTTP status codes in particular circumstances where the status codes SHALL map to particular states correctly, and only where the correct status code is not obvious. Other HTTP status codes may be used for other states as appropriate, and this particularly includes various authentication related status codes and redirects. Authentication redirects should not be interpreted to change the location of the resource itself (a common web programming error).

FHIR defines an OperationOutcome resource that can be used to convey specific detailed processable error information. For a few combinations of interactions and specific return codes, an OperationOutcome is required to be returned as the content of the response. The OperationOutcome may be returned with any HTTP 4xx or 5xx response, but is not required - many of these errors may be generated by generic server frameworks underlying a FHIR server.

2.1.0.5 Managing Return Content

In the interests of managing band-width, this specification allows clients to specify what kind of content to return.

2.1.0.5.1 conditional read

Clients may use the If-Modified-Since, or If-None-Match HTTP header on a read request. If so, they MUST accept either a 304 Not Modified as a valid status code on the response (which means that the content is unchanged since that date) or full content (either the content has not changed, or the server does not support conditional request).

Servers can return 304 Not Modified where content is unchanged since the If-Modified-Since date-time or the If-None-Match ETag specified or they can return the full content as normal. This optimisation is relevant in reducing bandwidth for caching purposes and servers are encouraged but not required to support this.

2.1.0.5.2 create/update/transaction

These operations are performed using POST,PUT and POST respectively, and it may be appropriate for a server to return either only a status code, or also return the entire resource that is the outcome of the create or update (which may be different to that provided by the client). In the case of transactions this means returning a Bundle with just the Bundle.entry.transactionResponse populated, and not the Bundle.entry.resource values.

The client can indicate whether the entire resource is returned using the HTTP return preference:

Prefer: return=minimal
Prefer: return=representation

The first of these two asks to return no body. The second asks to return the full resource. Servers SHOULD honour this header. In the absence of the header, servers may chose whether to return the full resource or not. Note that this setting only applies to succesful interactions. In case of failure, servers SHOULD always return a body that contains an OperationOutcome resource.

2.1.0.6 Content Types and encodings

The formal MIME-type for FHIR resources is application/xml+fhir or application/json+fhir. The correct mime type SHALL be used by clients and servers:

  • XML: application/xml+fhir
  • JSON: application/json+fhir

Servers SHALL support server-driven content negotiation as described in section 12 of the HTTP specification.

However in order to support various implementation limitations, servers SHOULD support the optional _format parameter to specify alternative response formats by their MIME-types. This parameter allows a client to override the header value when it is unable to set it correctly due to internal limitations. For the _format parameter, the values "xml", "text/xml", "application/xml", and "application/xml+fhir" SHALL be interpreted to mean the normative XML format defined by FHIR and "json", "application/json" and "application/json+fhir" SHALL be interpreted to mean the informative JSON format.

FHIR uses UTF-8 for all request and response bodies. Since the HTTP specification (section 3.7.1) defines a default character encoding of ISO-8859-1, requests and responses SHALL explicitly set the character encoding to UTF-8 using the charset parameter of the MIME-type in the Content-Type header. Requests MAY also specify this charset parameter in the Accept header and/or use the Accept-Charset header.

2.1.0.7 Support for Versions

Servers that support this API SHOULD provide full version support - that is, populate and track versionId correctly, support vread, and implement version aware updates. Supporting versions like this allows for related systems to track the correct version of information, and to keep integrity in clinical records. However, many current operational systems do not do this, and cannot easily be re-engineered to do so.

For this reason, Servers are allowed to not provide versioning support: this API does not enforce that they are supported. Clients may elect to only interact with servers that do provide full versioning support. Systems declare their support for versioning in their conformance statement.

2.1.0.8 read

The read interaction accesses the current contents of a resource. The interaction is performed by an HTTP GET command as shown:

  GET [base]/[type]/[id] {?_format=[mime-type]}

This returns a single instance with the content specified for the resource type. This url may be accessed by a browser. The possible values for the Logical Id (id) itself are described in the id type. The returned resource SHALL have an id element with a value that is the [id]. Servers SHOULD return an ETag header with the versionId and a Content-Location header with the response which is the full version specific url (see vread below) and a Last-Modified header.

Note: Unknown resources and deleted resources are treated differently on a read: A GET for a deleted resource returns a 410 status code, whereas a GET for an unknown resource returns 404. Systems that do not track deleted records will treat deleted records as an unknown resource.

2.1.0.9 vread

The vread interaction preforms a version specific read of the resource. The interaction is performed by an HTTP GET command as shown:

  GET [base]/[type]/[id]/_history/[vid] {?_format=[mime-type]}

This returns a single instance with the content specified for the resource type for that version of the resource. The returned resource SHALL have an id element with a value that is the [id], and a meta.versionId element with a value of [vid]. Servers SHOULD return an ETag header with the versionId and a Content-Location header with the response which is the full version specific url (see vread below) and a Last-Modified header.

The Version Id (vid) is an opaque identifier that conforms to the same format requirements as a Logical Id. The id may have been found by performing a history interaction (see below), by recording the version id from a content location returned from a read or from a version specific reference in a content model. If the version referred to is actually one where the resource was deleted, the server should return a 410 status code.

Servers are encouraged to support a version specific retrieval of the current version of the resource even if they do not provide access to previous versions. If a request is made for a previous version of a resource, and the server does not support accessing previous versions, it should return a 404 Not Found error, with an operation outcome explaining that history is not supported for the underlying resource type.

2.1.0.10 update

The update interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given id. The update interaction is performed by an HTTP PUT command as shown:

  PUT [base]/[type]/[id] {?_format=[mime-type]}

The request body SHALL be a Resource with an id element that has an identical value to the [id] in the URL. If the request body includes a meta, the server SHALL ignore the existing versionId and lastUpdated values. If the server supports versions, it SHALL populate the meta.versionId and meta.lastUpdated with the new correct values. Servers are allowed to review and alter the other metadata values, but SHOULD refrain from doing so (see metadata description for further information).

A server SHOULD accept the resource as submitted when accepts the update, and return the same content when it is subsequently read. However systems may not be able to do this; see the note on transactional integrity for discussion.

If the interaction is successful, the server SHALL return either a 200 OK HTTP status code if the resource was updated, or a 201 Created status code if the resource was created, with a Last-Modified header, and an ETag header which contains the new versionId of the resource. A Content-Location header that refers to the specific version created by the update interaction SHOULD also be returned. If the resource was created (i.e. the interaction resulted in a 201 Created), the server SHOULD return a Location header.

Note: Servers MAY choose to preserve XML comments, instructions, and formatting or JSON whitespace when accepting updates, but are not required to do so. The impact of this on digital signatures may need to be considered.

2.1.0.10.1 Rejecting Updates

Servers are permitted to reject update interactions because of integrity concerns or other business rules, and return HTTP status codes accordingly (usually a 422).

Common HTTP Status codes returned on FHIR-related errors (in addition to normal HTTP errors related to security, header and content type negotiation issues):

  • 400 Bad Request - resource could not be parsed or failed basic FHIR validation rules (or multiple matches were found for
  • 403 Not Authorised - authorization is required for the interaction that was attempted
  • 404 Not Found - resource type not supported, or not a FHIR end point
  • 405 Method Not allowed - the resource did not exist prior to the update, and the server does not allow client defined ids
  • 409/412 - version conflict management - see above
  • 422 Unprocessable Entity - the proposed resource violated applicable FHIR profiles or server business rules

Any of these errors should be SHOULD be accompanied by an OperationOutcome resource providing additional detail concerning the issue.

For additional information on how systems may behave when processing updates, refer to the Create and Update Behavior page.

2.1.0.10.2 Conditional updates

The conditional update operation allows a client to update an existing resource based on some identification criteria, rather than by logical id. To accomplish this, the client issues a PUT as shown:

  PUT [base]/[type]/?[search parameters]

When the server processes this update, it performs a search using its standard search facilities for the resource type, with the goal of resolving a single logical id for this request. The action it takes depends on how many matches are found:

  • No matches: The server performs a create operation
  • One Match: The server performs the update against the matching resource
  • Multiple matches: The server returns a 412 Precondition Failed error indicating the the client's criteria were not selective enough

This variant can be used to allow a stateless client (such as an interface engine) to submit updated results to a server, without having to remember the logical ids that the server has assigned. For example, a client updating the status of a lab result from "preliminary" to "final" might submit the finalized result using PUT /Observation?identifier=http://my-lab-system|123

Note that transactions and conditional create/update/delete are complex operations and it is not expected that every server will implement them.

2.1.0.11 Managing Resource Contention

Lost Updates, where two clients update the same resource, and the second overwrites the updates of the first, can be prevented using a combination of the ETag and If-Match header.

To support this usage, servers SHOULD always return an ETag header with each resource:

HTTP 200 OK
Date: Sat, 09 Feb 2013 16:09:50 GMT
Last-Modified: Sat, 02 Feb 2013 12:02:47 GMT
ETag: W/"23"
Content-Type: application/json+fhir

if provided, the value of the ETag SHALL match the value of the version id for the resource. Servers are allowed to generate the version id in whatever fashion that they wish, so long as they are valid according to the id data type, and are unique within the address space of all versions of the same resource. When resources are returned as part of a bundle, there is no ETag, and the versionId of the resource is used directly.

If the client wishes to request a version aware update, it submits the request with an If-Match header that quotes the ETag from the server:

PUT /Patient/347 HTTP/1.1
If-Match: W/"23"

If the version id given in the If-Match header does not match, the server returns a 412 Pre-condition failed status code instead of updating the resource.

Servers can require that clients provide an If-Match header by returning 412 Pre-condition failed status codes when no If-Match header is found.

2.1.0.12 delete

The delete interaction removes an existing resource. The interaction is performed by an HTTP DELETE command as shown:

  DELETE [base]/[type]/[id]

A delete interaction means that subsequent non-version specific reads of a resource return a 410 HTTP status code and that the resource is no longer found through search interactions. Upon successful deletion, or if the resource does not exist at all, the server should return 204 (No Content).

Whether to support delete at all, or for a particular resource type or a particular instance is at the discretion of the server based on the business rules that apply in its context. If the server refuses to delete resources of that type as a blanket policy, then it should return the 405 Method not allowed status code. If the server refuses to delete a resource because of reasons specific to that resource, such as referential integrity, it should return the 409 Conflict status code. Performing this interaction on a resource that is already deleted has no effect, and the server should return a 204 or 200 response. Resources that have been deleted may be "brought back to life" by a subsequent update interaction using an HTTP PUT.

Many resources have a status element that overlaps with the idea of deletion. Each resource type defines what the semantics of the deletion interactions are. If no documentation is provided, the deletion interaction should be understood as deleting the record of the resource, with nothing about the state of the real-world corresponding resource implied.

For servers that maintain a version history, the delete operation does not remove a resource's version history. From a version history respect, deleting a resource is the equivalent of creating a special kind of history entry that has no content and is marked as deleted.

2.1.0.12.1 Conditional deletes

The conditional delete operation allows a client to update an existing resource based on some identification criteria, rather than by logical id. To accomplish this, the client issues an HTTP DELETE as shown:

  DELETE [base]/[type]/?[search parameters]

When the server processes this update, it performs a search as specified using the standard search facilities for the resource type. The action it takes depends on how many matches are found:

  • No matches: The server returns 404 (Not found)
  • One Match: The server performs an ordinary delete on the matching resource
  • Multiple matches: The server returns a 412 Precondition Failed error indicating the the client's criteria were not selective enough

This variant can be used to allow a stateless client (such as an interface engine) to delete a resource on a server, without having to remember the logical ids that the server has assigned. For example, a client deleting a lab atomic result might delete the resource using DELETE /Observation?identifier=http://my-lab-system|123.

Note that transactions and conditional create/update/delete are complex operations and it is not expected that every server will implement them.

2.1.0.13 create

The create interaction creates a new resource in a server-assigned location. If the client wishes to have control over the id of a newly submitted resource, it should use the update interaction instead. The create interaction is performed by an HTTP POST command as shown:

  POST [base]/[type] {?_format=[mime-type]}

The request body SHALL be a FHIR Resource without an id element (this is the only case where a resource exists without an id element). If the request body includes a meta, the server SHALL ignore the existing versionId and lastUpdated values. The server SHALL populate the meta.versionId and meta.lastUpdated with the new correct values. Servers are allowed to review and alter the other metadata values, but SHOULD refrain from doing so (see metadata description for further information).

A server SHOULD accept the resource as submitted when it accepts the create, and return the same content when it is subsequently read. However some systems may not be able to do this; see the note on transactional integrity for discussion.

The server returns a 201 Created HTTP status code, and SHOULD also return a Location header which contains the new Logical Id and Version Id of the created resource version:

  Location: [base]/[type]/[id]/_history/[vid]

where [id] and [vid] are the newly created id and version id for the resource version. Servers SHOULD return an ETag header with the versionId and a Content-Location header with the response which is the full version specific url (see vread below) and a Last-Modified header.

When the resource syntax or data is incorrect or invalid, and cannot be used to create a new resource, the server returns a 400 Bad Request HTTP status code. When the server rejects the content of the resource because of business rules, the server returns a 422 Unprocessible Entity error HTTP status code. In either case, the server SHOULD include a response body containing an OperationOutcome with detailed error messages describing the reason for the error.

Common HTTP Status codes returned on FHIR-related errors (in addition to normal HTTP errors related to security, header and content type negotiation issues):

  • 400 Bad Request - resource could not be parsed or failed basic FHIR validation rules
  • 404 Not Found - resource type not supported, or not a FHIR end point
  • 422 Unprocessable Entity - the proposed resource violated applicable FHIR profiles or server business rules. This should be accompanied by an OperationOutcome resource providing additional detail

Note: Servers MAY choose to preserve XML comments, instructions, and formatting or JSON whitespace when accepting creates, but are not required to do so. The impact of this on digital signatures may need to be considered.

For additional information on how systems may behave when processing updates, refer to the Create and Update Behavior page.

2.1.0.13.1 Conditional create

The conditional create operation allows a client to create a new resource only if some equivalent resource does not already exist on the server. The client defines what equivalence means in this case by supplying a FHIR search query in an If-None-Exist header as shown:

  If-None-Exist: base/[type]?[search parameters]

When the server processes this update, it performs a search as specified using its standard search facilities for the resource type. The action it takes depends on how many matches are found:

  • No matches: The server processes the create as above
  • One Match: The server ignore the post and returns 200 OK
  • Multiple matches: The server returns a 412 Precondition Failed error indicating the the client's criteria were not selective enough

This variant can be used to avoid the risk of two clients creating duplicate resources for the same record. For example, a client posting a new lab result might specify If-None-Exist: /Observation?identifier=http://my-lab-system|123 to ensure it is does not create a duplicate record.

Note that transactions and conditional create/update/delete are complex operations and it is not expected that every server will implement them.

2.1.0.14 search

This interaction searches a set of resources based on some filter criteria. The interaction can be performed by several different HTTP commands.

  GET [base]/[type]{?[parameters]{&_format=[mime-type]}}

This searches all resources of a particular type using the criteria represented in the parameters.

Because of the way that some user agents and proxies treat GET and POST requests, in addition to the get based search method above, servers that support search SHALL also support a POST based search:

POST  [base]/[type]/_search{?[parameters]{&_format=[mime-type]}}

This has exactly the same semantics as the equivalent GET command. All these search interactions take a series of parameters that are a series of name'='value pairs encoded in the URL (or as an application/x-www-form-urlencoded submission for a POST). (See W3C HTML forms). Searches are processed as specified for the Search handling mechanism.

If the search fails, the return value is a status code 4xx or 5xx with an OperationOutcome. If the search succeeds, the return content is a Bundle with type = searchset containing the results of the search as a list of resources in a defined order. The result list can be long, so servers may use paging. If they do, they SHALL use the method described below (adapted from RFC 5005 (Feed Paging and Archiving) for breaking the list into pages if appropriate. The server MAY also return an OperationOutcome resource with additional information about the search; if one is sent it SHALL NOT include any errors, and it shall be marked with an entry mode of include.

2.1.0.14.1 Variant Searches

To search a compartment, either all possible resources, or for a particular resource type, respectively:

  GET [base]/[Compartment]/[id]/{*?[parameters]{&_format=[mime-type]}}
  GET [base]/[Compartment]/[id]/[type]{?[parameters]{&_format=[mime-type]}}

For example, to retrieve all the observation resources for a particular LOINC code associated with a particular encounter:

  GET [base]/Encounter/23423445/Observation?code=2951-2  {&_format=[mime-type]}

Note that there are a specific operations defined to support fetching an entire patient record or all record for an encounter.

Finally, it's possible to search all resources at once:

  GET [base]?[parameters]{&_format=[mime-type]}

When searching all resources at once, only the parameters defined for all resources can be used.

2.1.0.15 conformance

The conformance interaction retrieves the server's conformance statement that defines how it supports resources. The interaction is performed by an HTTP OPTIONS or a GET command as shown:

  GET [base]/metadata {?_format=[mime-type]}
  OPTIONS [base] {?_format=[mime-type]}

Applications SHALL return a Conformance Resource that specifies which resource types and interactions are supported for the GET command, and SHOULD do so for the OPTIONS command. If a 404 Unknown is returned from the GET, FHIR is not supported on the nominated service url. The GET command is defined because not all client libraries are able to perform an OPTIONS command. An ETag header SHOULD be returned with the conformance resource. The value of the header SHALL change if the conformance statement itself changes. In addition, a Content-Location header with a literal location where this version of the conformance statement is (and will continue to be) available MAY be returned. Additional parameters that are required to be returned with the OPTIONS command are defined in the OMG hData RESTful Transport specification.

The Conformance statement returned typically has an arbitrary id, and no meta element, though it is not prohibited.

In addition to this conformance operation, a server may also choose to provide the standard set of interactions (read, search, create, update) defined on this page for the Conformance Resource end point. This is different to the conformance operation:

conformance operationreturns a conformance statement describes the server's current operational functionality
Conformance end pointmanages a repository of conformance statements (e.g. the HL7 conformance statement registry)

All servers are required to support the conformance operation, but servers may choose whether they wish to support the conformance end-point, just like any other end point.

2.1.0.16 transaction

The transaction interaction submits a set of actions to perform on a server as a single atomic action. Multiple actions on multiple resources of the same or different types may be submitted, and they may be a mix of other operations defined on this page (e.g. read, search, create, update, delete, etc).

This is especially useful where one would otherwise need multiple interactions, possibly with a risk of loss of referential integrity if a later interaction fails (e.g. when storing a Provenance resource and its corresponding target resource, or, on document repositories, a document index entry and its accompanying document).

Note that transactions and conditional create/update/delete are complex operations and it is not expected that every server will implement them.

The transaction interaction is performed by an HTTP POST command as shown:

  POST [base] {?_format=[mime-type]}

The content of the post submission is a Bundle with Bundle.type = transaction. Each entry carries a transaction (Bundle.entry.transaction) that provides the HTTP details of the operation in order to inform the system processing the transaction what to do for the entry. If the HTTP operation is a PUT or POST, then the entry SHALL contain a resource for the body of the operation. The resources in the bundle are each processed separately as if they were an individual operation as otherwise described on this page, or for Extended Operations. The operations are subject to the the normal processing for each, including the meta element, verification and version aware updates, and transactional integrity.

Servers SHALL either accept all actions and return a 200 OK, along with a response bundle (see below), or reject all resources and return an HTTP 400 or 500 type response. It is not an error if the submitted bundle has no resources in it. The outcome of the processing the transaction SHALL NOT depend on the order of the resources in the transaction. A resource can only appear in a transaction once (by identity).

Processing Bundle Entries

Because of the rules that a transaction is atomic, that all operations pass or fail together, and that order of the entries doesn't matter, there is a particular order in which to process the operations:

  1. Process any POST operations
  2. Process any PUT operations
  3. Process any DELETE operations
  4. Process any GET operations

If any resource identities (including resolved identities from conditional update/delete) overlap in steps 1-3, then the transaction SHALL fail.

A transaction may include references from one resource to another in the bundle, including circular references where resources refer to each other. If the server assigns a new id to any resource in the bundle as part of the processing rules above, it SHALL also update any references to that resource in the same bundle as they are processed. References to resources that are not part of the bundle are left untouched. Version-specific references should remain as version-specific references after the references have been updated. Servers SHALL replace all matching links in the bundle, whether they are found in the resource ids, resource references, url elements, or <a href="" & <img src="" in the narrative.

2.1.0.16.1 Transaction Response

In order to allow the client to know the outcomes of processing the entry, and the identities assigned to the resources by the server, the server SHALL return a Bundle with type set to transaction-response that contains one entry for each entry in the transaction, in the same order, with the outcome of processing the entry.

Each entry element SHALL contain a transactionResponse element which details the outcome of processing the entry - the HTTP status code, and the location and ETag header values, which are used for identifying and versioning the resources. In addition, a resource may be included in the entry.

2.1.0.16.2 Accepting Other bundle types

A server may choose to accept bundle types other than transaction as transactions.

Bundles of type history inherently have the same structure as a transaction, and can be treated as one, so servers SHOULD accept a history bundle - this makes it possible to replicate data from one server to another easily. Note, however, that existing transaction boundaries are not represented in a history list, and a resource may occur more than once in a history list, so servers processing history bundles must have some strategy to manage this.

For other bundle types, should the server choose to accept them, there will be no transaction element (note that every entry will have a resource). In this case, the server treats the entry as either a create or an update operation, depending on whether it recognises the identity of the resource - if the identity of the resource refers to a valid location on the server, it should treat it as an update to that location. Note: this option allows a client to delegate the matching process to the server.

2.1.0.17 history

The history interaction retrieves the history of either a particular resource, all resources of a given type, or all resources supported by the system. These three variations of the history interaction are performed by HTTP GET command as shown:

  GET [base]/[type]/[id]/_history{?[parameters]&_format=[mime-type]}
  GET [base]/[type]/_history{?[parameters]&_format=[mime-type]}
  GET [base]/_history{?[parameters]&_format=[mime-type]}

The return content is a Bundle with type set to history containing the specified version history, sorted with oldest versions last, and including deleted resources. Each entry SHALL minimally contain a either a resource which holds the resource as it is at the conclusion of the operation, or a transaction with entry.transaction.method = DELETE. The transaction provides information about the operation that occurred to cause the new version. The principal reason it might not be missing is that the resource was changed by some other channel than via the RESTful interface. If the entry.transaction.method is a PUT or a POST, the entry SHALL contain a resource.

The operations create, update, and delete create history entries. Other operations do not (note that these operations may produce side-effects such as new AuditEvent resources; these are represented as create operations in their own right). A create operation is represented in a history operation in the following way:

  <entry>
    <resource>
      <Patient>
        <!-- the id of the created resource -->
        <id value="23424"/>
        <!-- snip -->
      </Patient>
    </resource>
    <transaction>
      <!-- POST: this was a create -->
      <method value="POST"/>
      <url value="Patient"/>
    </transaction>
  </entry>

Note that conditional creates, updates and deletes are converted to direct updates and deletes in a history list.

In addition to the standard _format parameter, the parameters to this interaction may also include:

_count : integersingleNumber of return records requested. The server is not bound to return the number requested, but cannot return more
_since : instantsingleOnly include resource versions that were created at or after the given instant in time

The history list can be restricted to a limited period by specifying a _since parameter which contains a full date time with time zone. Clients should be aware that due to timing imprecision, they may receive notifications of a resource update on the boundary instant more than once. Servers are not required to support a precision finer than by second.

The updates list can be long, so servers may use paging. If they do, they SHALL use the method described below for breaking the list into pages if appropriate, and maintain the specified _count across pages.

The history interaction can be used to set up a subscription from one system to another, so that resources are synchronized between them. Refer to the Subscription resource for an alternate means of system synchronization.

2.1.0.18 Transactional Integrity

When processing create and update operations, a FHIR server is not obliged to accept the entire resource as it is; when the resource is retrieved through a read operation subsequently, the resource may be different. The difference may arise for several reasons:

  • The server merged updated content with existing content
  • The server applied business rules and altered the content
  • The server does not fully support all the features or possible values of the resource

Note that there is no general purpose method to make merging with existing content or altering the content by business rules safe or predictable - what is possible, safe and/or required is highly context dependent. These kind of behaviors may be driven by security considerations. With regard to incomplete support, Clients can consult the server's base conformance statement profile references to determine which features or values the server does not support.

To the degree that the server alters the resource for any of the 3 reasons above, the FHIR server will create implementation consequences for the eco-system that it is part of, which will need to be managed (i.e. it will cost more). For this reason, servers SHOULD change the resource as little as possible. However due to the variability that exists within healthcare, this specification allows that servers MAY alter the resource on create/update.

Similarly, to the degree that an implementation context makes special rules about merging content or altering the content, that context will become more expensive to maintain.

Although these rules are stated with regard to servers, a similar concept applies to clients - to the degree that different client systems interacting with the server do not support the same feature set, the clients and/or the server will be forced to implement custom logic to prevent information from being lost or corrupted.

Some of these problems can be mitigated by following a pattern built on top of version-aware updates. In this pattern:

  • The server provides a read operation for any resource it accepts update operations on
  • Before updating, the client reads the latest version of the resource
  • The client applies the changes it wants to the resource, leaving other information intact (note the extension related rules around this)
  • The client writes the result back as an update operation, and is able to handle a 409 or 412 response (usually by trying again)

If clients follow this pattern, then information from other systems that they do not understand will be maintained through the update.

Note that it's possible for a server to choose to maintain the information that would be lost, but there is no defined way for a server to determine whether the client omitted the information because it wasn't supported (perhaps in this case) or whether it wishes to delete the information.

2.1.0.18.1 Conformance

Both client and server systems SHOULD clearly document how transaction integrity is handled.

DSTU TODO: how?

2.1.0.19 Paging

If servers provide paging for the results of a search or history interaction, they SHALL conform to this method (adapted from RFC 5005 (Feed Paging and Archiving) for sending continuation links to the client when returning a Bundle (e.g. with history and search). If the server does not do this, there is no way to continue paging.

This example shows the third page of a search result:

<Bundle xmlns="http://hl7.org/fhir">
  <!-- snip metadata -->
  <!-- This Search. url starts with base search, and adds the effective
    parameters, and additional parameters for search state. All searches
    SHALL return this value.

	  In this case, the search continuation method is that the server
    maintains a state, with page references into the stateful list.
	-->
  <link>
    <relation value="self">
    <url value="http://example.org/Patient?name=peter&stateid=23&page=3"/>
  </link>
  <!-- 4 links for navigation in the search. All of these are optional, but recommended -->

  <link>
    <relation value="first"/>
    <url value="http://example.org/Patient?name=peter&stateid=23&page=1"/>
  </link>
  <link>
    <relation value="previous"/>
    <url value="http://example.org/Patient?name=peter&stateid=23&page=2"/>
  </link>
  <link>
    <relation value="next"/>
    <url value="http://example.org/Patient?name=peter&stateid=23&page=4"/>
  </link>
  <link>
    <relation value="last"/>
    <url value="http://example.org/Patient?name=peter&stateid=23&page=26"/>
  </link>

  <!-- then the search results... -->
</Bundle>

The server need not use a stateful paging method as shown in this example - it is at the discretion of the server how to best ensure that the continuation retains integrity in the context of ongoing changes to the resources. An alternative approach is to use version specific references to the records on the boundaries, but this is subject to continuity failures when records are updated.

A server MAY inform the client of the total number of resources returned by the interaction for which the results are paged using the Bundle.total.

Note that for search, where _include can be used to return additional related resources, the total number of resources in the feed may exceed the number indicated in totalResults.

2.1.0.20 Intermediaries

The HTTP protocol may be routed through an HTTP proxy such as squid. Such proxies are transparent to the applications, though implementers should be alert to the effects of caching, particularly including the risk of receiving stale content. See the HTTP specification for further detail

Interface engines may also be placed between the consumer and the provider. These differ from proxies because they actively alter the content and/or destination of the HTTP exchange and are not bound the rules that apply to HTTP proxies. Such agents are allowed, but SHALL mark the http header to assist with troubleshooting.

Any agent that modifies an HTTP request or Response content other than under the rules for HTTP proxies SHALL add a stamp to the HTTP headers like this:

  request-modified-[identity]: [purpose]
  response-modified-[identity]: [purpose]

The identity SHALL be a single token defined by the administrator of the agent that will sufficiently identify the agent in the context of use. The header SHALL specify the agent's purpose in modifying the content. End point systems SHALL not use this header for any purpose. Its aim is to assist with system troubleshooting.

2.1.0.21 OMG hData RESTful Transport

This RESTful specification described here is based on the OMG Health RESTful specification (HData). In this regard, FHIR functions as a Record Format Profile as described in that specification. Note the following significant factors to be aware of:

  • FHIR maps the hData sections to resource types, and hData documents to resource instances. There are no subsections, and client systems are not able to create new sections, though compartments behave somewhat like sections
  • Because clients cannot submit new sections (POST to service URL), POST to the service URL has been re-used for the transaction interaction (difference under review)
  • FHIR does not (yet) define a root document. When defined, it will contain information about what the FHIR server has done (as opposed to a conformance statement, which describes what it is capable of doing)
  • Note that this specification does not repeat the rules in the hData RESTful Transport concerning the OPTIONS command on the service URL, but these rules (extra headers etc.) still apply

2.1.0.22 Summary

These tables present a summary of the interactions described here. Note that all requests may include an optional Accept header to indicate the format used for the response (this is even true for DELETE since an OperationOutcome may be returned).

Interaction PathRequest
Verb Content-Type Body Prefer Conditional
read /[type]/[id] GET N/A N/A N/A O: ETag, If-Modified-Since, If-None-Match
vread /[type]/[id]/_history/[vid] GET N/A N/A N/A N/A
update /[type]/[id] PUT R Resource O O: If-Match
delete /[type]/[id] DELETE N/A N/A N/A N/A
create /[type] POST R Resource O O: If-None-Exist
search /[type]? GET N/A N/A N/A N/A
/[type]/_search? POST application/x-www-form-urlencoded form data N/A N/A
search-all /_search? or /? GET N/A N/A N/A N/A
/_search? POST application/x-www-form-urlencoded form data N/A N/A
conformance / or /metadata OPTIONS or GET N/A N/A N/A N/A
transaction / POST R Bundle O N/A
history /[type]/[id]/_history GET N/A N/A N/A N/A
history-type /[type]/_history GET N/A N/A N/A N/A
history-all /_history GET N/A N/A N/A N/A
(operation) /$[name], /[type]/$[name] or /[type]/[id]/$[name] POST R ParametersN/A N/A
GET N/A N/A N/A N/A
POST application/x-www-form-urlencoded form data N/A N/A

Notes:

  • N/A = not present, R = Required, O = optional
  • For operations defined on all resources, including direct access to the meta element, see Resource Operations
InteractionResponse
Content-Type Body Location Content-Location Versioning Status Codes
read R R: Resource N/A R R: ETag, Last-Modified 200, 404, 410
vread R R: Resource N/A R R: ETag, Last-Modified 200, 404
update R if body O: Resource (Prefer) R on create R R: ETag, Last-Modified 200, 201, 400, 404, 405, 409, 412, 422
delete R if bodyO: OperationOutcome N/A N/A N/A 200, 204, 404, 405, 409, 412
create R if body O : Resource (Prefer) R R R: ETag, Last-Modified 201, 400, 404, 405, 422
search R R: Bundle N/A N/A N/A 200, 403?
search-all R R: Bundle N/A N/A N/A 200, 403?
conformance R R: Conformance N/A O N/A 200, 404
transaction R R: Bundle N/A N/A N/A 200, 400, 404, 405, 409, 412, 422
history R R: Bundle N/A N/A N/A 200
history-type R R: Bundle N/A N/A N/A 200
history-all R R: Bundle N/A N/A N/A 200
(operation) R R: Parameters/ResourceN/A N/A N/A 200

Note: this table lists the status codes described here, but other status codes are possible as described by the HTTP specification. Additional codes that are likely a server errors and various codes associated with authentication protocols.