DSTU 2 Overview

This topic describes the DSTU 2 Final (1.0.2) specification.

Schema

All API access is over HTTPS. See Service Root URL for more information on URL format. All data is sent and received as JSON.

$ curl -i -H "Accept: application/json+fhir" https://fhir-open.cerner.com/dstu2/ec2458f2-1e24-41c8-b71b-0e701af7583d/metadata
HTTP/1.1 200 OK
Date: Tue, 05 Jan 2016 20:02:23 GMT
cache-control: no-cache
vary: Origin,User-Agent
strict-transport-security: max-age=631152000
x-xss-protection: 1; mode=block
x-request-id: 637dd651-6943-4d45-8e8a-0577da7640a2
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
Content-Type: application/json+fhir; charset=utf-8
Transfer-Encoding: chunked

{
  "resourceType": "Conformance",
  "text": {
    "status": "generated",
    "div": "<div>Generated Conformance Statement</div>"
  },
  "url": "https://fhir-open.cerner.com/dstu2/ec2458f2-1e24-41c8-b71b-0e701af7583d/metadata",
  "name": "Cerner Conformance Statement",
  "status": "draft",
  "publisher": "Cerner",
  "date": "2015-12-03T00:00:00+00:00",
  "description": "Describes capabilities of this server",
  "kind": "instance",
  "fhirVersion": "1.0.2",
  "acceptUnknown": "no",
  "format": [
    "json"
  ],
  "rest": [
    {
      "mode": "server",
      "documentation": "All the functionality defined in FHIR",
      "security": {
        "cors": true
      },
      "resource": [
        {
          "type": "AllergyIntolerance",
          "interaction": [
            {
              "code": "read"
            },
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "_id",
              "type": "token",
              "documentation": "A single or comma separated list of AllergyIntolerance ids. It is a required field if patient field is not given"
            },
            {
              "name": "patient",
              "type": "reference",
              "documentation": "Who the sensitivity is for. It is a required field if _id field is not given"
            },
            {
              "name": "status",
              "type": "token",
              "documentation": "Certainty of the allergy or intolerance"
            }
          ]
        },
        {
          "type": "Condition",
          "interaction": [
            {
              "code": "read"
            },
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "_id",
              "type": "token",
              "documentation": "A single or comma separated list of Condition ids. It is a required field if patient field is not given"
            },
            {
              "name": "patient",
              "type": "reference",
              "documentation": "The patient who has the condition. It is a required field if _id field is not given"
            },
            {
              "name": "clinicalstatus",
              "type": "token",
              "documentation": "A list of desired clinical statuses of the condition"
            },
            {
              "name": "category",
              "type": "token",
              "documentation": "The category of the condition"
            }
          ]
        },
        {
          "type": "Device",
          "interaction": [
            {
              "code": "read"
            },
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "patient",
              "type": "reference",
              "documentation": "The patient who has the device affixed. It is a required field if _id field is not given"
            },
            {
              "name": "_id",
              "type": "token",
              "documentation": "A single or comma separated list of Device ids. It is a required field if patient field is not given"
            }
          ]
        },
        {
          "type": "DocumentReference",
          "interaction": [
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "patient",
              "type": "reference",
              "documentation": "The patient the document is about"
            },
            {
              "name": "type",
              "type": "token",
              "documentation": "The type of the document"
            }
          ]
        },
        {
          "type": "MedicationOrder",
          "interaction": [
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "patient",
              "type": "reference",
              "documentation": "The identity of a patient to list dispenses for. It is a required field"
            },
            {
              "name": "status",
              "type": "token",
              "documentation": "The status of the med, may be a list separated by commas. (Active and draft statuses must be queried separately from completed, on-hold, and stopped statuses. The superseded and entered-in-error statuses are not supported). It is a required field"
            },
            {
              "name": "timing-boundsperiod-end",
              "type": "date",
              "documentation": "The stop time of the order. Must be prefixed by 'le' (currently only support querying for orders completed prior to a certain time). Not accepted when querying active or draft orders"
            },
            {
              "name": "_count",
              "type": "number",
              "documentation": "The number of items to include in a page. Currently ignored if querying for active or draft statuses"
            }
          ]
        },
        {
          "type": "MedicationStatement",
          "interaction": [
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "patient",
              "type": "reference",
              "documentation": "The identity of a patient to list statements for. It is a required field."
            },
            {
              "name": "status",
              "type": "token",
              "documentation": "One or more medication statement status values separated by commas."
            },
            {
              "name": "effectivedate",
              "type": "date",
              "documentation": "The date-time which should fall within the period the patient was taking (or not taking) the medication. Must be prefixed by 'ge'."
            },
            {
              "name": "_count",
              "type": "number",
              "documentation": "The maximum number of results to include in a page."
            }
          ]
        },
        {
          "type": "Patient",
          "interaction": [
            {
              "code": "read"
            },
            {
              "code": "search-type"
            }
          ],
          "searchParam": [
            {
              "name": "_id",
              "type": "token",
              "documentation": "The logical resource id associated with the resource (must be supported by all servers). It is a required field if no birthdate, identifier, name or telecom field is given"
            },
            {
              "name": "birthdate",
              "type": "date",
              "documentation": "The patient's date of birth. It is a required field if no _id, identifier, name or telecom field is given"
            },
            {
              "name": "identifier",
              "type": "token",
              "documentation": "A patient identifier. It is a requried field if no _id, birthdate, name or telecom field is given"
            },
            {
              "name": "name",
              "type": "string",
              "documentation": "A portion of either family or given name of the patient. It is a required field if no _id, birthday, identifier or telecom field is given"
            },
            {
              "name": "telecom",
              "type": "string",
              "documentation": "The value in any kind of telecom details of the patient. It is a required field if no _id, birthdate, identifier or name is given"
            },
            {
              "name": "_count",
              "type": "number",
              "documentation": "The maximum number of results to return"
            }
          ]
        }
      ]
    }
  ]
}

Blank fields are omitted.

All timestamps are returned in FHIR standard date/dateTime formats.

Media Types

Oracle Cerner supports FHIR standard defined media types for JSON content:

application/json+fhir
application/json

We encourage you to explicitly request this accept type via the Accept header.

Common Application Errors

See the FAQs and Common Issues page for more information on common issues identified when validating applications to run on our platform.

Client Errors

There are seven possible types of client errors on API calls that receive request bodies:

  1. Failing to send a required query parameter will result in a 400 Bad Request response.

    HTTP/1.1 400 Bad Request
    
    no supported search parameters provided
  2. Requesting the secure endpoint (non-open) without valid credentials will result in a 401 Unauthorized response.

    HTTP/1.1 401 Unauthorized
  3. Requesting data from an unknown instance or an instance where the application is not authorized will result in a 403 Forbidden response.

    HTTP/1.1 403 Forbidden
    
    Tenant not valid or accessible
  4. Requesting a resource which does not exist will result in a 404 Not Found response.

    HTTP/1.1 404 Not Found
  5. Requesting a media type other than JSON will result in a 406 Not Acceptable response.

    HTTP/1.1 406 Not Acceptable
    Content-Length: 0
  6. Performing an update with an out-of-date version id will result in a 409 Conflict Error response.

    HTTP/1.1 409 Conflict Error
  7. Performing an add or update with syntactically correct JSON body which is invalid according to business rules will result in a 422 Unprocessable Entity response.

    HTTP/1.1 422 Unprocessable Entity

Operation Outcomes

An OperationOutcome may be returned to provide additional context to an error. The tables below describes common OperationOutcomes and their causes.

Retrieve/Search

HTTP Status Cause Severity Code

500

Response is missing a required field

fatal

required

Create/Update

HTTP Status Cause Severity Code

422

Body contained unsupported fields

error

business-rule

422

Body contained modifier extensions

error

extension

422

Body contained implicit rules

error

not-supported

Handling Required Fields

  1. Missing fields required by the HL7 FHIR specification or any missing status field will result in a 500 Internal Server Error and an OperationOutcome.

    {
       "resourceType": "OperationOutcome",
       "issue": [
         {
           "severity": "fatal",
           "code": "required",
           "location": [
             "/f:AllergyIntolerance/f:status"
           ]
         }
       ]
     }  
  2. Missing fields required by HL7 profiles such as Argonaut (DSTU 2) or US Core (STU 3) will result in a DataAbsentReason.

    {
       "coding": [
         {
           "extension": [
             {
               "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
               "valueCode": "unknown"
             }
           ]
         }
       ]
     }
  3. Patient consumers requesting a resource with a status of entered-in-error may result in a DataAbsentReason.

    {
       "coding": [
         {
           "extension": [
             {
               "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
               "valueCode": "masked"
             }
           ]
         }
       ]
     }
  4. Missing Coding or CodeableConcept fields with a required value set binding will result in a DataAbsentReason, though it may return a text component.

    {
       "coding": [
         {
           "extension": [
             {
               "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
               "valueCode": "unknown"
             }
           ]
         }
       ],
       "text": "Auth (Verified)"
     }

Filtered Data for Patient or Proxy Access

When accessing data with a patient persona, some data may be filtered as compared to system or provider access. Resources with a status of "entered-in-error" will result in either some fields being filtered or returned with a data absent reason with a valueCode of masked. Fields that may contain sensitive information will be filtered such as non-instructional notes. For proxy users, regulatory laws or policies may restrict parental or guardian access to adolescent health records and these regulations vary from state to state.

General Security Filtering

Not all data can be accessed by all applications or users. Encounter or organization security, privileges, and preference may filter data based on the build in the domain.

HTTP Verbs

Where possible, the FHIR standard strives to use appropriate HTTP verbs for each action.

Verb Description

GET

Used for retrieving resources.

POST

Used for creating resources.

PUT

Used for updating resources.

Authorization

We have an endpoint secured with OAuth 2.0 with support for SMART Applications. Refer to the extensions on the Conformance.rest.security element in our server metadata.

Each resource interaction documents the type of authentication acceptable (patient, provider, and/or system).

See the Authorization Framework page for details on how to authorize with our server.

Pagination

The pagination links are included in the Bundle when a resource returns more items than the Bundle page size. It is important to follow these Link header values instead of constructing your own URLs.

{
  "resourceType": "Bundle",
  "id": "f22ca456-19a7-45ce-8586-0079495783ef",
  "type": "searchset",
  "link": [
    {
      "relation": "self",
      "url": "https://fhir-open.cerner.com/dstu2/ec2458f2-1e24-41c8-b71b-0e701af7583d/Observation?subject%3APatient=12742400&_count=50"
    },
    {
      "relation": "next",
      "url": "https://fhir-open.cerner.com/dstu2/ec2458f2-1e24-41c8-b71b-0e701af7583d/Observation?subject%3APatient=12742400&pageContext=35d95fe0-03bf-426c-bc35-2533f7fde4eb&direction=NEXT"
    }
  ],
  ...
}

The possible relation values are:

Name Description

self

Shows the URL of the current page of results.

next

Shows the URL of the immediate next page of results.

previous

If paging, shows the URL of the previous page of results.

Concurrency

Developers need to account for data concurrency within the response. The FHIR specification states:

The results of a search operation are only guaranteed to be current at the moment the operation is executed. After the operation is executed, ongoing actions performed on the resources against which the search was executed will render the results increasingly stale. The significance of this depends on the nature of the search, and the kind of use that is being made of the results.

This is particularly relevant when the server is returning the results in a series of pages. It is at the discretion of the search engine of how to handle ongoing updates to the resources while the search is proceeding.

When results are returned in a series of pages, you may see the same resource id on subsequent pages. Developers need to take this situation into account by filtering by resource id and only return the latest version of that resource id. Displaying duplicate resource ids or any other manipulation may misrepresent the data thus impacting clinical decision support and patient safety.

Cross Origin Resource Sharing

The API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. You can read the CORS W3C Recommendation, or this intro from the HTML 5 Security Guide.

Here's a sample GET request sent from the Origin http://example.com:

$ curl -X GET -i -H "Origin: http://example.com" https://fhir-ehr-code.cerner.com/dstu2/ec2458f2-1e24-41c8-b71b-0e701af7583d/metadata
HTTP/1.1 200 OK
Access-Control-Allow-Methods: DELETE, GET, POST, PUT, PATCH, OPTIONS, HEAD
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag, Content-Location, Location, X-Request-Id, WWW-Authenticate, Date
Access-Control-Max-Age: 0

This is what a CORS preflight request looks like:

$ curl -X OPTIONS -i -H "Origin: http://example.com" -H "Access-Control-Request-Headers: authorization,content-type" -H "Access-Control-Request-Method: GET" https://fhir-ehr-code.cerner.com/dstu2/ec2458f2-1e24-41c8-b71b-0e701af7583d/metadata
HTTP/1.1 200 OK
Access-Control-Allow-Methods: DELETE, GET, POST, PUT, PATCH, OPTIONS, HEAD
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag, Content-Location, Location, X-Request-Id, WWW-Authenticate, Date
Access-Control-Max-Age: 0
Access-Control-Allow-Headers: authorization, content-type