R6 Ballot (2nd Draft)

Publish-box (todo)

FHIR Infrastructure icon Work Group Maturity Level: 1 Standards Status: Draft

Implementation Note: The FHIR Asynchronous Interaction Request Pattern API is under active development. Participate in design discussions at chat.fhir.org icon

All of the interactions defined in the RESTful API are described as synchronous operations - that is, the client makes a query and waits for the server to respond with the outcome in the HTTP response. This pattern is not always suitable when significant server side processing is necessary.

The asynchronous request pattern, based on rfc 7240 icon, caters to this use case and is applicable in Operations and Defined Interactions that are not processed synchronously or may take a lot of time to process. For example, servers that accept a high volume sensor data and queue it for saving, or an operation that re-indexes the data in a server to add a new search parameter. Servers may choose which interactions the pattern should be supported on (if at all).

For use cases that may return a large amount of data, see Asynchronous Bulk Data Request.

The request will support the HTTP methods, URLs, headers and other parameters that normally apply, but servers SHALL also support the Prefer header described below. The Accept header in the request will dictate the format of the Bundle Resource returned when the request completes successfully or an OperationOutcome Resource when it fails, as well any the format for any OperationOutcome Resources returned to indicate a transient polling error while the request is being processed.

If an _outputFormat parameter is supplied as part of the request, the server SHALL respond using the Asynchronous Bulk Data Request pattern, or if this pattern is not supported by the server for the current request type, SHALL return an error and OperationOutcome Resource.

  • Accept (string)

    Specifies the format of the optional OperationOutcome Resource response to the kick-off request. A client SHOULD provide this header. A server may support any subset of the Serialization Format Representations. If omitted, the server MAY return an error or MAY process the request and return a format selected by the server format.

  • Prefer (string, required)

    Specifies whether the response is immediate or asynchronous. Setting this to respond-async triggers this async pattern.

  • HTTP Status Code of 202 Accepted
  • Content-Location header with the absolute URL of an endpoint for subsequent status requests (polling location)
  • Optionally, a OperationOutcome Resource in the body

After an asynchronous request has been started, a client MAY send a http DELETE request to the URL provided in the Content-Location header to cancel the request. Following the delete request, when subsequent requests are made to the polling location, the server SHALL return a 404 Not Found error and an associated OperationOutcome Resource.

  • HTTP Status Code of 202 Accepted
  • Optionally a FHIR OperationOutcome in the body

After an asynchronous request has been started, the client MAY poll the status URL provided in the Content-Location header by issuing HTTP GET requests to the location.

A client SHOULD follow an exponential backoff icon approach when polling for status. A server SHOULD supply a Retry-After icon header with a with a delay time in seconds (e.g., 120 to represent two minutes) or a http-date (e.g., Fri, 31 Dec 1999 23:59:59 GMT). When provided, a client SHOULD use this information to inform the timing of future polling requests. The server SHOULD keep an accounting of status queries received from a given client, and if a client is polling too frequently, the server SHOULD respond with a 429 Too Many Requests status code in addition to a Retry-After header, and optionally a OperationOutcome Resource with further explanation. If excessively frequent status queries persist, the server MAY return a 429 Too Many Requests status code and terminate the session. Other standard HTTP 4XX as well as 5XX status codes may be used to identify errors as mentioned.

  • HTTP Status Code of 202 Accepted
  • Optionally an X-Progress header with a text description of the status of the request that is less than 100 characters. The format of this description is at the server's discretion and MAY be a percentage complete value, or MAY be a more general status such as "in progress". The client MAY parse the description, display it to the user, or log it.
  • HTTP status code of 4XX or 5XX
  • The body of the response SHOULD be a OperationOutcome Resource. If this is not possible (for example, the infrastructure layer returning the error is not FHIR aware), the server MAY return an error message in another format and include a corresponding value for the Content-Type header.

Servers SHOULD NOT use status request failures to indicate a problem processing the original request. Rather, status request failures SHOULD use a transient code from the IssueType valueset when populating the OperationOutcome Resource issue.code element to indicate to the client that it should retry the request at a later time.

  • HTTP status of 200 OK
  • A body containing a Bundle Resource with a type of batch-response.

The outcome of the kick-off request SHALL be present as the first entry in the bundle. A successful completion of the status request SHOULD be used whenever processing has completed, regardless of whether the underlying interaction has succeeded or failed. A server SHOULD use the status and outcome elements of Bundle.entry[0].response to communicate any processing errors.

For example, if a client asynchronously invokes a hypothetical $example operation but omits a required parameter, the server would respond with a 200 OK on the status request once processing is complete, and would include a Bundle.entry[0].response.code element with a value of 400 Bad Request and a Bundle.entry[0].response.outcome with a OperationOutcome Resource containing details about the error.

Example output bundle:

{
  "resourceType": "Bundle",
  "type": "batch-response",
  "entry": [{
    "response": {
        "status": "200 OK", 
        "location": "Observation/123"
        // additional fields if needed
        //  * etag
        //  * lastModified
        //  * outcome
    },
    "resource": {
      // populated whenever a non-asynchronous
      // interaction would have included a resource in the
      // response body -- e.g. if client initially specified
      // `Prefer: return=representation`
      "resourceType": "Observation",
      "id": "123", 
      // ... snipped for brevity
    }
  }]
}