Skip to main content

Documentation Index

Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt

Use this file to discover all available pages before exploring further.

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
curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
  -H "Authorization: Bearer pk_xxx" \
  -H "X-Spree-Token: abc123" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{"variant_id": "variant_xxx", "quantity": 1}'
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.

Supported Endpoints

EndpointActions
POST /cartsCart creation
PATCH /carts/:idCart updates
POST /carts/:id/completeOrder completion
POST /carts/:id/itemsAdding items to cart
POST /carts/:id/payment_sessionsPayment session creation
PATCH /carts/:id/payment_sessions/:id/completePayment completion
POST /carts/:id/coupon_codesApplying coupon codes
POST /carts/:id/store_creditsApplying store credits
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 per API key — different API keys can use the same idempotency key without conflict
  • Cached responses expire after 24 hours

Response Headers

When a cached response is replayed, the API sets:
Idempotent-Replayed: true
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:
{
  "error": {
    "code": "idempotency_key_reused",
    "message": "This Idempotency-Key has already been used with different request parameters."
  }
}

Key Too Long

Keys longer than 255 characters return a 400 error:
{
  "error": {
    "code": "invalid_request",
    "message": "Idempotency-Key must be 255 characters or less."
  }
}

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:
import { createClient } from '@spree/sdk'

const client = createClient({
  baseUrl: 'http://localhost:3000',
  publishableKey: 'pk_xxx',
})

// Add item to cart with idempotency key
await client.carts.items.create(cartId, {
  variant_id: 'variant_xxx',
  quantity: 1,
}, {
  idempotencyKey: '550e8400-e29b-41d4-a716-446655440000',
})

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:
MechanismPreventsScope
Idempotency keysDuplicate operations from retriesPer-request deduplication
Optimistic locking (state_lock_version)Concurrent modificationsConflict detection between clients
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.