Skip to content

Long-running operations

Occasionally, a service may need to expose an operation that takes a significant amount of time to complete. In these situations, it is often a poor user experience to simply block while the task runs; rather, it is better to return some kind of promise to the user, and allow the user to check back in later.

The long-running request pattern is roughly analogous to a Future in Python or Java, or a Node.js Promise. Essentially, the user is given a token that can be used to track progress and retrieve the result.

Operations that might take a significant amount of time to complete:

  • must return 202 Accepted on successful submission to indicate the request has been accepted for processing.
  • must return an Operation object (see Interface Definitions) in the response body.
  • must match other AEP guidance that would apply to the method otherwise.
  • may include a Location header pointing to the operation status endpoint.

Example:

POST /documents/123/publications
202 Accepted
Location: /operations/op_abc123xyz
Content-Type: application/json
{
"id": "op_abc123xyz",
"state": "pending",
"metadata": {
"createdTime": "2025-12-02T10:30:00Z"
}
}

The service must provide a GET /operations/{operationId} endpoint to query the status of the operation. This endpoint:

  • must return 200 OK with an Operation object (see Interface Definitions) when the operation exists.
  • must return 404 Not Found when the operation does not exist (e.g., expired or invalid ID).

The service should provide a GET /operations endpoint to list operations. This endpoint:

  • may support filtering.
  • must follow standard pagination guidelines if implemented.

The Operation object returned:

  • must include the current state of the operation.
  • should include progress information in the metadata field when available (e.g., percentage complete, items processed).
  • must include the operation result in the result field when state is succeeded.
  • must include error details in the errors array when state is failed.

APIs may include additional state values if needed, but must document them clearly.

APIs may support cancelling long-running operations when feasible. Cancellation:

  • must be implemented via POST /operations/{operationId}:cancel.
  • must return 200 OK with the updated Operation object if the operation was successfully canceled.
  • must return 404 Not Found if the operation does not exist.
  • may not take effect immediately; the operation state should transition to canceled once cancellation is complete.

Not all operations can be safely canceled. APIs must document which operations support cancellation.

A resource may accept multiple requests that will work on it in parallel but is not obligated to do so:

  • Resources that accept multiple parallel requests may place them in a queue rather than work on the requests simultaneously.
  • A resource that does not permit multiple requests in parallel (denying any new request until the one that is in progress finishes) must return 409 Conflict if a user attempts a parallel request, and include an error message explaining the situation.

APIs may allow their operation resources to expire after sufficient time has elapsed after the request completed.

  • Expired operations should return 404 Not Found or 410 Gone when queried.
  • The expiration policy must be documented.
  • APIs should retain operation records long enough for clients to retrieve results, even with retry delays.

Errors that prevent a long-running request from starting must return an error response, similar to any other method.

Errors that occur during the operation’s execution must be reflected in the Operation object with state: "failed" and detailed error information in the errors array.

Operation:
type: object
description: Represents a long-running operation.
required:
- id
- state
- createdTime
properties:
id:
type: string
description: The unique identifier for this operation.
state:
type: string
enum:
- pending
- running
- succeeded
- failed
- cancelled
description: The current state of the operation.
metadata:
type: object
description:
Service-specific metadata about the operation, such as progress
information.
additionalProperties: true
result:
type: object
description: The result of the operation when state is 'succeeded'.
additionalProperties: true
errors:
type: array
description: Error details when state is 'failed'.
items:
type: object
properties:
code:
type: string
message:
type: string
  • The response body schema must be an Operation object as described above.
  • The response body schema may contain an object property named metadata to hold service-specific metadata associated with the operation, for example, progress information and common metadata such as create time. The service should define the contents of the metadata object in a separate schema, which should specify additionalProperties: true to allow for future extensibility.
  • The result property must be a schema that defines the success response for the operation. For operations that typically return 204 No Content (such as delete), result should be defined as an empty object schema. For operations that typically return a response body, result should contain a representation of the created or modified resource, or a summary of the operation’s outcome.