API Overview
Release1.0.1
1.0.1
StatusTRIAL
TRIAL
Date17 Oct 2019
17 Oct 2019
API Endpoint{baseUrl}/v1
{baseUrl}/v1
© 2003 - 2019 The openEHR Foundation | |
---|---|
The openEHR Foundation is an independent, non-profit community organisation, facilitating the sharing of health records by consumers and clinicians via open standards-based implementations. | |
Licence | Creative Commons Attribution-NoDerivs 3.0 Unported. https://creativecommons.org/licenses/by-nd/3.0/ |
Support | Issues: Problem Reports Web: specifications.openEHR.org |
Amendment Record
Issue | Details | Raiser, Implementer | Completed | |||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Release-1.0.1 | ||||||||||||||||||||||||||||||||||||||||||
2.4 | SPECITS-33: Add reference to Simplified Data Template (SDT) format specification | I McNicoll, T Beale, S Iancu | 17 Oct 2019 | |||||||||||||||||||||||||||||||||||||||
2.3 | SPECITS-32: Fix typos and minor documentary errors | J Smolka, P Pazos, T Beale, S Iancu | 19 Jul 2019 | |||||||||||||||||||||||||||||||||||||||
2.2 | SPECITS-24: Added changelog | J Smolka, S Iancu | 12 May 2019 | |||||||||||||||||||||||||||||||||||||||
SPECITS-25, SPECITS-29: Change layout and structure | J Smolka, S Iancu | 12 May 2019 | ||||||||||||||||||||||||||||||||||||||||
2.1 | Update links to new openEHR specifications website | S Iancu | 16 Dec 2018 | |||||||||||||||||||||||||||||||||||||||
Release-1.0.0 |
Preface
Purpose
This specification describes service endpoints, resources, functions and operations as well as details of requests and responses that interacts with an openEHR API in a RESTful manner.
Related Documents
Prerequisite documents for reading this document include:
Related documents include:
Status
This specification is in the TRIAL
state. It might not be complete and can still be subject to changes before the final release.
Users are encouraged to comment on and/or advise on these paragraphs as well as the main content.
The development version of this document can be found at https://specifications.openehr.org/releases/ITS-REST/latest.
Feedback
Feedback may be provided on the technical mailing list or on github repo.
Issues may be raised on the specifications Problem Report tracker.
To see changes made due to previously reported issues, see the ITS component Change Request tracker.
Trademarks
- ‘openEHR’ is a trademark of the openEHR Foundation
Glossary and conventions
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in BCP 14 RFC 2119 RFC 8174 when, and only when, they appear in all capitals, as shown here.
Types defined by openEHR specification are always capitalized (e.g. EHR, COMPOSITION, VERSIONED_OBJECT, etc.) when used in this specification. For a list of all available types or a particular type definition please refer to the class index.
Throughout this specification, a set of short terms is being used as described below:
Term | Description |
---|---|
API | Application Programmer Interface |
REST | Representational state transfer, a type of Web service that allows clients to access and manipulate textual representations of Web resources. |
AQL | openEHR’s Archetype Query Language |
SEMVER | Semantic Versioning 2.0.0 |
{baseUrl} |
The base URL of the openEHR APIs; the value depends on the implementation (e.g. https://api.best-ehr-sys.io/rest ) |
UUID |
A universally unique identifier as described by RFC 4122 (e.g. 8849182c-82ad-4088-a07f-48ead4180515) |
ehr_id |
The value for an EHR identifier, stored under EHR.ehr_id.value, usually an UUID or a GUID (e.g. 7d44b88c-4199-4bad-97dc-d78268e01398) |
versioned_object_uid |
The value of a VERSIONED_OBJECT unique identifier, stored under VERSIONED_OBJECT.uid.value (e.g. 8849182c-82ad-4088-a07f-48ead4180515) |
version_uid |
The value of a VERSION unique identifier, stored under VERSION.uid.value (e.g. 8849182c-82ad-4088-a07f-48ead4180515::openEHRSys.example.com::2) |
preceding_version_uid |
The value of a previous VERSION unique identifier, used usually for PUT or DELETE methods (e.g. 8849182c-82ad-4088-a07f-48ead4180515::openEHRSys.example.com::1) |
version_at_time |
Time specifier used to retrieve the VERSION at a given time; the value is in the extended ISO8601 format (e.g. 2015-01-20T19:30:22.765+01:00) |
HTTP Methods used in this specification are described by RFC 7231. HTTP Status codes are described by RFC 7231 and in the IANA Status Code Registry.
See design considerations section section for more details on how some HTTP methods and status codes MUST be used by an openEHR REST API implementation to achieve good interaction between services and clients in the spirit of this specification.
JSON format is used in many of the example below, but this does not imply that XML might not be supported by the same service endpoint. See below how data representation MUST be done and negotiated.
Design considerations ¶
Options and conformance ¶
Headers
Accept: application/json
Headers
Content-Type: application/json
Allow: GET, POST, PUT, DELETE, OPTIONS
Body
{
"solution": "openEHRSys",
"solution_version": "v0.9",
"vendor": "My-openEHR",
"restapi_specs_version": "v1.0.1",
"conformance_profile": "STANDARD",
"endpoints": [
"/ehr",
"/definition",
"/query"
]
}
HTTP headers ¶
This specification is using a few standard and custom HTTP headers that are described below.
The openEHR-VERSION
and openEHR-AUDIT_DETAILS
headers
When it comes to committing content to an openEHR system, for all change-controlled resources (e.g. COMPOSITION, EHR_STATUS, FOLDER, etc.) the services are performing versioning under the hood. Thus, the ‘native’ way of committing content is to wrap it as VERSION and use CONTRIBUTION.
But in order to keep things simpler and consistent, service MUST allow PUT
, POST
and DELETE
methods also directly on these change-controlled resources.
However, internally, these operations MUST be executed using the ‘native’ way with CONTRIBUTION.
In order to allow clients to provide committal metadata, services MUST accept openEHR-VERSION
and openEHR-AUDIT_DETAILS
request custom headers.
For clients, it is RECOMMENDED to provision these headers based on authentication and authorization runtime data.
Below is a complex example of these request headers used in a PUT action to update a COMPOSITION:
openEHR-VERSION.lifecycle_state: code_string="532"
openEHR-AUDIT_DETAILS.change_type: code_string="251"
openEHR-AUDIT_DETAILS.description: value="An updated composition contribution description"
openEHR-AUDIT_DETAILS.committer: name="John Doe", external_ref.id="BC8132EA-8F4A-11E7-BB31-BE2E44B06B34", external_ref.namespace="demographic", external_ref.type="PERSON"
None of these headers are mandatory, but whatever is provided it MUST be merged with the default VERSION and VERSION.audit_details attributes on commit runtime.
Below a list of code_string
values and their meaning (taken from openEHR terminology):
header | code | value / meaning |
---|---|---|
openEHR-VERSION.lifecycle_state | 532 | complete |
openEHR-VERSION.lifecycle_state | 553 | incomplete |
openEHR-VERSION.lifecycle_state | 523 | deleted |
openEHR-AUDIT_DETAILS.change_type | 249 | creation |
openEHR-AUDIT_DETAILS.change_type | 250 | amendment |
openEHR-AUDIT_DETAILS.change_type | 251 | modification |
openEHR-AUDIT_DETAILS.change_type | 252 | synthesis |
openEHR-AUDIT_DETAILS.change_type | 523 | deleted |
openEHR-AUDIT_DETAILS.change_type | 666 | attestation |
openEHR-AUDIT_DETAILS.change_type | 253 | unknown |
The If-Match
header and accidental overwrites
The use case of this is described by RFC 7232.
If-Match: 8849182c-82ad-4088-a07f-48ead4180515::openEHRSys.example.com::2
This HTTP request header SHOULD be used by the clients to prevent accidental overwrites when multiple user
agents might be acting in parallel on the same resource. This is only required by a small set of resources of this specification,
as in most of the other cases the preceding_version_uid
path segment is instead required in order to prevent such accidental overwrites.
In case a service receives this header and the condition evaluates to false
, it MUST respond with
HTTP status code 412 Precondition Failed
and return also latest version_uid
in the Location
and ETag
response headers.
The Location
header
This response header indicates the resource location (URL). According to RFC 7231, it is used to refer to a specific resource in relation to the response. The type of relationship is defined by the combination of request method and status code semantics. Services MUST return this header whenever a create or update operation was performed, but it MAY return this header on other operation or action. Example:
Location: {baseUrl}/ehr/347a5490-55ee-4da9-b91a-9bba710f730e/composition/8849182c-82ad-4088-a07f-48ead4180515::openEHRSys.example.com::2
See representation details negotiation section for more details on how use this header.
Services MAY generate resource URL as specified by DV_URI/DV_EHR_URI format, and if this feature is supported then the services
MUST use openEHR-uri
response header. Example:
openEHR-uri: ehr:/347a5490-55ee-4da9-b91a-9bba710f730e/compositions/87284370-2D4B-4e3d-A3F3-F303D2F4F34B
The Prefer
header
This request header MAY be used by clients for resource representation negotiation. See more details on representation details negotiation section.
The ETag
and Last-Modified
headers
These headers are mainly related to whether or not a returned resource may be cacheable. Their purpose is to give clients information about the state of the requested resources.
According to RFC 7232,
The “ETag” header field in a response provides the current entity-tag for the selected representation, as determined at the conclusion of handling the request. An entity-tag is an opaque validator for differentiating between multiple representations of the same resource, regardless of whether those multiple representations are due to resource state changes over time, content negotiation resulting in multiple representations being valid at the same time, or both.
The ETag
response HTTP header contains a string token that the server associates with a resource in order to
uniquely identify the state of that resource over its lifetime. The value of the token changes as soon as the resource changes.
An example of such header value format is:
ETag: 8849182c-82ad-4088-a07f-48ead4180515::openEHRSys.example.com::2
Servers MAY choose their own format for this header, but the recommended value is the unique identifier of the requested resource (e.g. VERSIONED_OBJECT.uid.value, VERSION.uid.value, EHR.ehr_id.value, etc).
The Last-Modified
response HTTP header contains the datetime of the last modification of targeted resource
which should be taken from VERSION.commit_audit.time_committed.value.
An example of such header value format is:
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
These two headers SHOULD be present in all responses targeting VERSION, VERSIONED_OBJECT or other resources that have similar unique identifier.
HTTP status codes ¶
To indicate the status of the request or the executed operation, one of the following subset of the HTTP status codes RFC 7231 MUST be used:
Code | Reason-Phrase | Meaning, usecase and details |
---|---|---|
200 | OK | The request succeeded, payload sent in a 200 response depends on the request method |
201 | Created | The request has been fulfilled and has resulted in one or more new resources being created |
204 | No content | The request has been fulfilled and there is no additional content to send in the response payload body |
400 | Bad request | The service cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, syntactically invalid content) |
401 | Unauthorized | If the service requires authorization, this indicates that the request has not been applied because it lacks valid authentication credentials for the target resource |
403 | Forbidden | The service understood the request but refuses to authorize it |
404 | Not found | The origin service did not find the target resource or is not willing to disclose that one exists |
405 | Method Not Allowed | The method received in the request-line is known by the origin service but not supported by the target resource |
406 | Not Acceptable | The target resource does not have a current representation that would be acceptable to the user |
408 | Request Timeout | Request maximum execution time is reached, therefore the server aborted the request |
409 | Conflict | Indicates that the request could not be processed because it might generate a duplicate or a conflict |
412 | Precondition Failed | One or more conditions given in the request header fields evaluated to false when tested on the server |
415 | Unsupported Media Type | The service is refusing the request because the payload is in a format not supported by this method on the target resource |
422 | Unprocessable Entity | The request was well-formed but was unable to be followed due to semantic errors |
500 | Internal Server Error | The service encountered an unexpected condition that prevented it from fulfilling the request |
501 | Not Implemented | The service does not support the functionality required to fulfill the request |
Meaning of these codes may be further detailed (nuanced) in this specification by particular responses. If required, other status codes MAY be used by implementations as long as their usecase is not conflicting or overlapping with above codes.
Status code 400 indicates a bad request or generic client-side error, used when no other 4xx error code is appropriate. The client SHOULD NOT repeat the request without modifications.
In case of errors (HTTP status codes 400-500), the services MAY return more details (if Prefer: return=representation
request header is present).
Example:
some codes/messages https://github.com/ppazos/cabolabs-ehrserver/wiki/API-error-codes-and-messages and http://veratechnas1.synology.me:13606/InstanceValidator/rules.html
{
"message": "Error message",
"code": 90000,
"errors": [
{
"_type": "DV_CODED_TEXT",
"value": "Error message",
"defining_code": {
"terminology_id": {
"value": "local"
},
"code_string": "9000"
}
},
{
"_type": "DV_CODED_TEXT",
"value": "Secondary error message",
"defining_code": {
"terminology_id": {
"value": "local"
},
"code_string": "8000"
}
}
]
}
Data representation ¶
Services MUST support at least one of the openEHR XML or JSON formats (described below) for resource representation.
XML Format
When resources representation is serialized as XML, the request payload as well as the result MUST be valid against published XSDs.
A client MAY use the header Content-Type: application/xml
in the requests to specify the XML payload format.
If the service cannot process the request payload as XML format is not supported, it MUST respond with HTTP status code415 Unsupported Media Type
.
The client SHOULD use the Accept: application/xml
request header in order to specify the expected XML response format.
If the service cannot fulfill this aspect of the request, it MUST respond with HTTP status code 406 Not Acceptable
.
Proper header Content-Type: application/xml
MUST be present in the response of the service
unless the response has no body (HTTP status code 204).
JSON Format
When resources representation is serialized as JSON, the request payload as well as the result SHOULD be valid against published JSON-Schemas.
Note: The JSON-Schema project is under development.
Attribute names must be lowercase snake_case names as specified in the equivalent RM type. For example:
{
"category": {
"value": "event",
"defining_code": {
"terminology_id": {
"value": "openehr"
},
"code_string": "433"
}
}
}
Metadata attributes (those that are not also RM attributes) will always be prefixed by a '_'
.
One example is the _type
attribute, which should be used to specify the RM type whenever polymorphism
is involved or the underlying definition in RM type is abstract
(dynamic type is different from the static type).
This follows same rule as for XML typing.
The value of this attribute MUST be the uppercase class name from the RM specification. For example:
{
"_type": "DV_TEXT",
"value": "Hello world!"
}
The RM attributes (even required ones) that are Null
, empty list or empty arrays SHOULD be absent when serialized as JSON.
The order of attributes in the resource MAY follow the order of attributes in the RM specification of the type of the resource, but this is not mandatory.
A client MAY use the header Content-Type: application/json
in the requests to specify the JSON payload format.
If the service cannot process the request payload as JSON format is not supported, it MUST respond with HTTP status code 415 Unsupported Media Type
.
The client SHOULD use the Accept: application/json
request header in order to specify the expected JSON response format.
If the service cannot fulfill this aspect of the request, it MUST respond with HTTP status code 406 Not Acceptable
.
Proper header Content-Type: application/json
MUST be present in the response of the service
unless the response has no body (HTTP status code 204).
Alternative data formats
Creating data instances according to canonical XML or JSON format is not always straightforward, particularly for developers with minimal exposure to openEHR, and various alternatives have been used in the past to simplify the job of content creation and committal for application developers.
There is an initiative exploring and documenting these alternative formats, which specifications can be consulted at Simplified Data Template (SDT) page.
Note: The specification of Simplified Data Template is under development.
In order to use these formats, content negotiation SHOULD be done in the same manner as for the canonical XML or JSON format above,
but instead of application/xml
or application/json
, clients and servers MUST use:
-
application/openehr.nc.flat+json
for near-canonical RM Simplified Data Template (ncSDT) as JSON, flat format originally devised for the EtherCIS project, -
application/openehr.wt.flat+json
for simplified IM Simplified Data Template (simSDT) as JSON, based on the ‘flat’ version of the ‘web template’ format originally created by Marand for the Better platform (see also their ‘examples’). -
application/openehr.tds2+xml
for TDS simplification of RM as XML, based on the ‘TDS/TDD’ format originally created by Ocean Health Systems (see also the this wiki page and the TDD2canonical project).
Other alternative formats may be added in the future, depending on innovative impact, simplicity, popular demand or adoption rate. Current alternative formats might not be supported once they become obsolete or superseded by newer formats.
Datetime format
Query parameters and path segments that are date, datetime, or time, MUST always use the extended ISO8601 format, e.g. 2016-06-23T13:42:16.117+02:00.
Timezone SHOULD be only supplied when needed and that when not supplied, the local timezone is assumed.
Any date, datetime or time value provided by a create or update action inside the COMPOSITION content will be preserved as it was sent by client (i.e. if COMPOSITION was saved as narrow format, it will always return the way it was). However, the strongly RECOMMENDED format is to use the ISO8601 extended format. This is to enable time information in EHRs shared across timezones to be computed properly.
Representation details negotiation ¶
When using the HTTP methods to create or update a resource, the service SHOULD give clients the option of returning either a complete
representation of the (modified) resource, or a minimal or no content in the payload response (assuming the operation was successfully completed).
See RFC 7240 for more details on how achieve this using Prefer
header.
The client MAY choose any of the following:
-
send
Prefer: return=minimal
to inform the service that prefers only a minimal response to a successful request. ALocation
header indicating the direct URL to access the resource MUST be part of the service response. If there is no payload content to be returned, the service SHOULD use HTTP status code204 No Content
. -
send
Prefer: return=representation
to inform the service that prefers a full representation response to a successful request. ALocation
header indicating the direct URL to access the resource MAY be part of the service response and the payload content SHOULD include a full representation.
In case no Prefer
header is present in request, the default response policy is return=minimal
.
Another preference is related to following and resolving OBJ_REF identifiers. Under some circumstances a client
MAY indicate that prefers response containing full or partial resource representation instead of references to resources using OBJ_REF.
A typical case is a list of COMPOSITIONs part of an EHR, which, strictly following RM specification, should always return
list of OBJ_REF, but sometimes clients prefers to get COMPOSITIONs.
Services that have this capability implemented SHOULD accept and honor Prefer: resolve_refs
request header.
Prefer: return=representation, resolve_refs
Generated with aglio on 17 Oct 2019