Idempotent requests

Send an Idempotency-Key with every write, so that a retried request returns the original result instead of applying the same change twice.

An idempotency key identifies one write request. When you send the same request again with the same key, the platform returns the response to the first request instead of carrying out the change again. This makes a write safe to retry when you don't know whether it arrived, for example after a timeout or a dropped connection.

Send a key with every write

Send the Idempotency-Key header with every POST, PUT, PATCH, and DELETE request. Use a new random UUID for every new request:

Stop an instance with an idempotency key
KEY=$(uuidgen)
curl -X POST "https://<api-host>/api/v1/scopes/<project-id>/compute/instances/<instance-id>/actions/stop" \
  -H "Authorization: Bearer $PC_TOKEN" \
  -H "Idempotency-Key: $KEY"
  • <api-host>, <project-id>, <instance-id>: the API's host name, the project's ID, and the instance's ID.
  • KEY: the key. Keep it until you know the result, so that a retry can send the same value.

Some operations accept only a UUID as the key, for example the operations on users, invitations, role assignments, service accounts, and API tokens. Another value returns 422 Unprocessable Entity with the code VALIDATION_FAILED and the field Idempotency-Key.

Important

With an API token or a service account key, the key is required on every POST request that creates a resource and answers 202 Accepted: for example, creating an instance, a volume, a network, a floating IP, a load balancer, a bucket, a snapshot, a role, or a commitment, cloning a volume, or restoring a snapshot into a new volume. Without the key, such a request is refused with 400 Bad Request and the code IDEMPOTENCY_KEY_REQUIRED. The API gateway doesn't make up a key for it, because a retry would get another key and create a second resource. The API reference marks the header as required on these operations.

On every other write, the key is optional: DELETE, PATCH, and PUT requests, and actions on an existing resource, such as starting an instance or attaching a volume. When you send a key, the platform answers a repeated key as described below. When you don't, the request is carried out once, without replay protection, and a retry can apply the change again. Send a key with these writes too, and generate it yourself, so that a retry can send the same value.

How the platform answers a repeated key

For an operation that uses the key, the platform compares a repeated key with the request that first used it. Two requests are the same when they have the same method, the same path, and the same body. The order of the fields in a JSON body doesn't matter.

You sendThe platform answers
The same key and the same request, after the first request finishedThe status and body of the first response. The change isn't carried out again.
The same key and the same request, while the first request is still being processed409 Conflict with "retryable": true. Wait a moment, and send the request again with the same key.
The same key with a different request409 Conflict with the code CONFLICT. Use a new key for a new request.

Some details of a replay:

  • Status and body only. A replay repeats the first response's status and body. Response headers of the first response, such as ETag, aren't repeated.
  • Changed resources. The replay comes before the request is checked again, so it's returned even if the resource has changed since. For example, a retried delete of a resource that's already gone returns the first response, not 404 Not Found.
  • Interrupted requests. If the first request stopped while it was being processed, retries with its key can return 409 Conflict with "retryable": true for up to 2 minutes.

How long a key lasts

The platform keeps the record of a key for at least 24 hours after the first request. Send your retries within 24 hours.

After 24 hours, don't reuse the key. Depending on the operation, the platform then refuses it with 409 Conflict and a message that the key has expired, returns the first response again, or treats the request as a new one.

Operations that don't use the key

Some operations ignore the key, and the API reference doesn't list the Idempotency-Key header for them. When you retry them, the request is carried out again, with these results:

OperationResult of a retry
Updating an instance, a volume, a network, a subnet, a router, a network interface, or a security groupThese updates require If-Match. If the first update was applied, the retry returns 412 Precondition Failed, because the version changed. Read the resource to check the result.
Replacing the tags of an instance, a volume, an image, or an instance snapshotThe same tags are set again. If you sent If-Match, the retry returns 412 Precondition Failed.
Rotating the signing secret of a notification channel, or the temporary URL key of Object StorageThe secret or key is rotated again.
Sending a test notification or a verification email for a notification channelThe message is sent again.

Retry a write safely

  1. Generate a UUID before you send the write, and store it with the request.
  2. If the request times out, the connection drops, or you receive 429 Too Many Requests or a 5xx status, send the same request with the same key.
  3. If you receive 409 Conflict with "retryable": true, wait, and send it again with the same key.
  4. When you have the result, use a new key for your next request, even if that request is identical. For example, creating a second, identical instance needs its own key.

Back off between retries. After a 429 Too Many Requests response, wait at least the number of seconds in its Retry-After header. Before you retry an operation that doesn't use the key, check whether the first request was applied. For the status codes, see Errors.

On this page