Skip to main content
The Store API supports idempotency keys on mutating endpoints. This lets you safely retry requests without risking duplicate side effects — for example, adding an item to cart twice or creating duplicate payments due to network timeouts.

How It Works

Include an Idempotency-Key header with a unique value (e.g., a UUID) on any supported request. The API will:
  1. First request — process normally and cache the response for 24 hours
  2. Duplicate request (same key, same parameters) — return the cached response without re-executing the operation
  3. Key reuse with different parameters — return a 422 error to prevent misuse
If the client retries this exact request with the same idempotency key, the API returns the original response with an Idempotent-Replayed: true header — without adding the item again.

Who A Cached Response Belongs To

A cached response is only ever returned to the caller that produced it, so the request has to say who that caller is. One of these identifies them:
  • the customer’s access token (Authorization: Bearer ...), for a signed-in shopper
  • the cart token (X-Spree-Token), for a guest working on a cart they already hold
  • a secret key (sk_...), for a server-to-server caller on the Admin API
Retry with the same credentials you sent the first time. A replay answers from the cache without running the request again, so it never re-checks your access — a retry that drops or swaps a credential is treated as a different caller and runs for real. Your publishable key (pk_...) does not count. Every visitor to your storefront sends the same one, so a key value that two shoppers happen to share — checkout-1, an order number, a timestamp — would hand one shopper the other’s response, cart token included. A request that carries none of the credentials above still runs exactly as it always has — it is simply never cached, so the Idempotency-Key header has no effect on it. Guests are not second-class here: a guest holds a cart token from the moment their cart exists, which covers the whole of checkout, including the steps where a duplicate costs money.

Supported Endpoints

Every one of these is replayable for a guest as well as for a signed-in shopper, because every one of them is reached with the cart’s token. The exception is creating the cart itself: there is no cart yet, so a guest has no token to present and the key is ignored — a retry may leave behind a second, empty cart. Sign the shopper in, or accept the spare cart. Idempotency keys are ignored on GET, DELETE, and other non-supported actions.

Key Requirements

  • Must be a string of 255 characters or less
  • Should be unique per distinct operation (UUIDs are recommended)
  • Keys are scoped to the caller and the store, so two callers can use the same key value without conflict
  • Cached responses expire after 24 hours

Response Headers

When a cached response is replayed, the API sets:
You can use this header to detect replayed responses in your application or logging.

Error Handling

Key Reuse with Different Parameters

If you send a request with an idempotency key that was previously used with different request parameters (different body, different path), the API returns a 422 error:

Key Too Long

Keys longer than 255 characters return a 400 error:

Server Errors

5xx responses are not cached. If the server fails to process your request, you can safely retry with the same idempotency key and the request will be re-executed.

SDK Usage

The Spree SDK supports idempotency keys via the idempotencyKey option:

Best Practices

  • Generate a new key for each distinct operation. Use a UUID (v4) or another random identifier. Never reuse keys across different operations.
  • Store the key before sending the request. If the request fails due to a network error, retry with the same key to ensure the operation is only performed once.
  • Don’t use idempotency keys for GET requests. GET requests are naturally idempotent and the API ignores the header on read-only endpoints.
  • Let keys expire naturally. Cached responses expire after 24 hours. Don’t rely on idempotency keys for longer-term deduplication.

Relationship with Optimistic Locking

The Store API also uses optimistic locking via the state_lock_version field on orders. These mechanisms complement each other: Use both together for robust checkout flows: idempotency keys protect against network retries, while state_lock_version detects when another client has modified the order.