Idempotent Requests
The Magnolia API supports idempotency for all authenticated POST and PATCH requests using the Idempotency-Key header, following the established draft RFC.
Why Use Idempotent Requests?
Idempotency prevents duplicate operations when network issues or timeouts occur. For example:
- Network timeout: Your request succeeds on the server, but you never receive the response
- Retry logic: Your application automatically retries failed requests
- User error: A user clicks "Submit" multiple times
With idempotent requests, retrying with the same Idempotency-Key will return the same result without creating duplicates.
Which Methods Support Idempotency?
| HTTP Method | Idempotency Support | Notes |
|---|---|---|
POST | ✅ Supported via Idempotency-Key header | Required for safe retries |
PATCH | ✅ Supported via Idempotency-Key header | Required for safe retries |
GET | ✅ Inherently idempotent | No header needed |
DELETE | ✅ Inherently idempotent | No header needed |
How to Make an Idempotent Request
1. Generate a Unique Key
Generate a random, unique key for your request. A UUID v4 is recommended:
Example: 550e8400-e29b-41d4-a716-446655440000
2. Add the Header
Include the Idempotency-Key header with your request:
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
3. Make Your Request
Perform your POST or PATCH request normally. If you retry with the same key, you'll get the same response.
Best Practices
1. Generate Keys Client-Side
Always generate idempotency keys on the client side. This ensures you have the same key available for retries.
// Good: Generate once, reuse for retries
const idempotencyKey = crypto.randomUUID();
await retryableRequest(data, idempotencyKey);
// Bad: Generate new key on each retry
await retryableRequest(data, crypto.randomUUID());
2. Store Keys for Long Operations
For long-running operations, store the idempotency key alongside the operation:
// Store the key with the pending operation
const operation = {
id: 'op_123',
data: accountData,
idempotencyKey: crypto.randomUUID(),
status: 'pending'
};
await saveToDatabase(operation);
// Use the stored key for retries
await createAccount(operation.data, operation.idempotencyKey);
3. Use Unique Keys Per Operation
Never reuse idempotency keys across different operations:
// Good: Different operations, different keys
const key1 = crypto.randomUUID();
await createAccount(accountData, key1);
const key2 = crypto.randomUUID();
await createContact(contactData, key2);
// Bad: Reusing the same key
const key = crypto.randomUUID();
await createAccount(accountData, key);
await createContact(contactData, key); // Don't do this!
4. Handle Key Expiration
Idempotency keys expire after 24 hours. If an operation might take longer than 24 hours, be prepared to generate a new key:
const MAX_KEY_AGE = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
function shouldRegenerateKey(keyTimestamp) {
return Date.now() - keyTimestamp > MAX_KEY_AGE;
}
How It Works
When you send a request with an Idempotency-Key:
- First request: The server processes the request and stores the result with the key
- Duplicate request: If you retry with the same key within 24 hours, the server returns the stored result without reprocessing
- After 24 hours: The key expires and a new request would be processed as new
Important Notes
- Optional but recommended: Using idempotency keys is currently optional but highly recommended for production applications
- Expiration: Keys expire after 24 hours in all environments
- Only for mutations: Use idempotency keys only for
POSTandPATCHrequests - Case-sensitive: Idempotency keys are case-sensitive
- Maximum length: Keys can be up to 255 characters (UUID v4 is 36 characters)
Learn More
For more details on the idempotency standard, see draft-ietf-httpapi-idempotency-key-header-06.