Introduction
Some operations do not finish inside a single request. This extension defines how an endpoint signals that the client should wait, then send the same request again. The signal is a tuple.
Activation
An endpoint activates this extension by including the deferred flag in its flags array. When the flag is present, a response MAY be the tuple defined below. Clients that implement this extension MUST check for the flag and, when it is present, follow the client behavior in this document.
The endpoint's returns describes the result. It does not describe the deferral, and it does not have to be object. A package writer MAY declare any type, including object.
This flag does not change the shape of a successful response. It MAY appear alongside other endpoint flags.
Response
When an endpoint defers, the response body MUST be a JSON array of two elements:
["DEFER", 1000]
| Position and type | Description |
|---|---|
First string | Required. The code DEFER. A client MUST compare this code case-insensitively. DEFER, Defer, and defer are the same code. |
Second number | Required. How long the client MUST wait, in milliseconds, before sending the same request again. The value MUST be greater than or equal to 0. |
The array MUST contain these two elements, in this order. Servers MUST NOT omit or reorder them. For forward compatibility, clients MUST read the tuple by position and MUST ignore any additional elements beyond the second.
A response whose body is not this tuple is not a deferral.
Client behavior
After a response from an endpoint whose flags include deferred, a client MUST:
If the body is not an array of at least two elements, the first element is not a string, or the first element does not match
DEFERunder a case-insensitive comparison, the response is not a deferral. The client MUST stop and surface it. It MUST NOT send the request again.If the second element is not a number, or is less than
0, the client MUST NOT send the request again and SHOULD surface an error.Wait the number of milliseconds given by the second element, measured from when the response was received. A value of
0means the client sends the request again immediately.Send the same request again.
Same request
The request the client sends again MUST be the request that produced the deferral: the same URL, the same headers, and the same body. The client MUST NOT change the path, the query string, the Authorization header, the Api-Version header, or the JSON body. If the original request had no Authorization header, the new request MUST NOT add one. If the original request had no Api-Version header, the new request MUST NOT add one.
Repeated deferral
If that request is also a deferral, the client MUST apply this behavior again, using the new second element. The client continues until a response is not a deferral, and surfaces that response to the caller.
Example
This example requests an export that is not ready yet. export has the deferred flag. The first response is a deferral, so the client waits 1000 milliseconds and sends the same request again. The second response is the result. The package is versioned and the endpoint requires a bearer token. Both requests carry the same URL, the same Authorization value, the same Api-Version, and the same body.
Initial request
POST /export
Content-Type: application/json
Accept: application/json
Authorization: Bearer tok_abc123
Api-Version: 2
{
"report_id": "report_9f3"
}
Deferred response
["DEFER", 1000]
The client waits 1000 milliseconds.
Resent request
POST /export
Content-Type: application/json
Accept: application/json
Authorization: Bearer tok_abc123
Api-Version: 2
{
"report_id": "report_9f3"
}
The URL, the bearer token, the version, and the body are unchanged.
Example package definition
{
"base_url": "https://api.example.com",
"name": "ExamplePackage",
"flags": ["versioned"],
"version": "2",
"versions": ["1", "2"],
"docs": "Example API. export may answer with DEFER until the report is ready.",
"endpoints": [
{
"name": "export",
"returns": ["object"],
"flags": ["deferred", "bearer_auth"],
"docs": "Exports a report. May respond with DEFER until the export is ready.",
"arguments": [
{
"name": "report_id",
"type": "string",
"flags": ["required"],
"docs": "Identifier of the report to export."
}
]
}
]
}