Overview of asynchronous calls
Synchronous calls
By default, calls made to Cloud API are synchronous. The caller application submits the request and waits for a response. This is depicted in the following diagram.
- The caller application sends a request to Cloud API. In the diagram, the request
is a POST for a resource named
someResource
. The request has a set of request headers and may have a payload. - Cloud API processes the request synchronously.
- Assuming the request is successful, Cloud API provides the response. The response also has a set of response headers and may have a payload.
Asynchronous calls
For some calls, it can be problematic to wait for a synchronous response. For example, quoting a large commercial policy may take several minutes, and the API Gateway may time out before the quote can be completed and returned to the caller.
To address these situations, you can execute a Cloud API call asynchronously. Broadly speaking, there are three phases to an asynchronous call. In practice, this could occur with fewer than or more than three calls.
Submitting the call
For an asynchronous call, the request is almost identical to a synchronous call. The
only difference is that the request object includes an additional
Prefer
request header indicating the desire for an asynchronous
response.
If the call is well-formed, Cloud API provides an initial response.
- The status of the response is "202 Accepted", indicating that the request has been accepted.
- The response body is empty.
- The response includes a
GW-Async-Location
header. The header's value is a path for an Async API endpoint that the caller can use to retrieve information about the original request.
This is depicted in the following diagram.
- The caller application sends a request to Cloud API. The request object includes a request header indicating to process the call asynchronously.
- Cloud API accepts the request. But it does not immediately process it.
- Cloud API provides a response. The response includes a header with an Async API
/requests
path that can be used to retrieve:- Information about the initial request.
- The response to the initial request, once it is available.
Determining when the call has been processed
After the call has been submitted, the caller application uses the Async API
/requests
path from the initial response to retrieve information
about the original request. This path takes the form of
/async/v1/requests/<asyncRequestId>
.
The response to the /requests
call always includes the following
information:
- The
requestMethod
andrequestPath
of the original request - The
status
of the original request, which can be set to:Accepted
- The request is still waiting to be processed.InProgress
- The request is being processed, but processing is not yet complete.Complete
- The request has been processed.
- The
startTime
of the original request
If the original request has been completed, then the following information is also included:
- The
completionTime
of the original request - The
responseStatus
andresponseHeaders
- If the response's format is
application/json
, then the response itself is included in theresponseBodyJson
field
Example response for a call that has not been completed
The following is a portion of the /requests
response for a
asynchronous call that has not yet been completed.
{
"data": {
"attributes": {
"requestMethod": "POST",
"requestPath": "/admin/v1/users",
"responseStatus": 202,
"startTime": "2022-07-12T16:53:12.365Z",
"status": {
"code": "Accepted",
"name": "Accepted"
}
}
}
}
Example response for a call that is complete
The following is a portion of the /requests
response for a
asynchronous call that is complete.
{
"data": {
"attributes": {
"completionTime": "2022-07-12T16:53:16.073Z",
"requestMethod": "POST",
"requestPath": "/admin/v1/users",
"responseBodyJson": {
"data": {
"attributes": {
...
"username": "asyncUser99",
"vacationStatus": {
"code": "atwork",
"name": "At work"
}
},
"checksum": "321dff263827cbbd772c26676398d8ae",
"links": {
...
}
}
},
"responseHeaders": {
"Cache-Control": [
"must-revalidate",
"post-check=0",
"pre-check=0",
"max-age=0",
"no-store",
"no-cache"
],
"Content-Type": [
"application/json;charset=UTF-8"
],
"GW-Checksum": [
"321dff263827cbbd772c26676398d8ae"
],
"Location": [
"/admin/v1/users/pc:ScaA3kB5cImBkuh7bxjNn"
],
"X-Correlation-ID": [
"d516344d-5769-4964-adb7-79eaca41e4a2"
],
...
},
"responseStatus": 201,
"startTime": "2022-07-12T16:53:12.365Z",
"status": {
"code": "Complete",
"name": "Complete"
}
}
...
}
}
Polling until the original request is complete
The caller application can poll Cloud API periodically until it receives a response whose status is Complete. This is depicted in the following diagram.
- The caller application sends a GET
/async/v1/requests/{asyncRequestId}
request to Cloud API. The path comes from the header of the initial response. - The Cloud API response includes information about the original request. If the status is Accepted or In Progress, the caller application must re-submit the GET after an appropriate interval.
When the response includes a status of Complete, the caller can retrieve the response to the original request. There are multiple ways that it can be retrieved.
Retrieving the response using /requests/{asyncRequestId}
The /requests
endpoint returns an AsyncRequest
resource. This resource includes a responseBodyJson
attribute. If the
original request has a status of Complete, and if the response's type is
application/json
, then this attribute contains the response payload
for the initial request.
This is depicted in the following diagram.
4. The caller application sends a GET
/async/v1/requests/{asyncRequestId}
request to Cloud API. The
acyncRequestId
comes from the header of the initial response.
5. The Cloud API response includes information about the original request.
When the status is Complete, the response includes the original request's response if
the response type is application/json
.
Note that the GET /async/v1/requests/{asyncRequestId}
request could
return a response of Complete the first time it is submitted or on a subsequent try.
Retrieving the response from /requests/{asyncRequestId}/response
There is also a /requests/{asyncRequestId}/response
endpoint. For
completed requests, this endpoint returns the original response as if the call had been
executed synchronously. This endpoint is useful when:
- The response type is something other than
application/json
, and therefore is not included in the GET/async/v1/requests/{asyncRequestId}
response. - The caller application wants the work with the response as it would normally appear,
as opposed to having to extract it from within the
responseBodyJson
attribute of a larger data envelope.
This is depicted in the following diagram.
6. The caller application sends a GET
/async/v1/requests/{asyncRequestId}/response
request to Cloud
API.
7. The Cloud API response includes the original response, as if the request had been executed synchronously.
When the original call is complete, the response to GET
/async/v1/requests/{asyncRequestId}/response
has the same status
code, response body (if any), and response headers as if the caller were getting a
synchronous response to the original request.
For example, if the original request was a POST that created a new activity, the GET
request to retrieve the response might return a 201 response code and have a
Location
header. If the original request failed because of a
validation error, the GET request to retrieve the response might have a 400 status code
and a response body with details of the errors.