API Idempotency
Prevent duplicate operations with idempotency keys
API Idempotency
Use idempotency keys to safely retry requests without creating duplicate operations.
What is idempotency?
An idempotent operation produces the same result whether executed once or multiple times. Idempotency keys allow you to retry failed requests without risk of duplicate payments.
Using idempotency keys
Include an Idempotency-Key header with a unique value:
const payment = await plexy.payments.create(
{
amount: 5000,
currency: 'USD',
payment_method: 'pm_card_visa',
},
{
idempotencyKey: 'order_12345_payment',
},
);Or with curl:
curl -X POST https://api.plexypay.com/v2/payments \
-H "x-api-key: Bearer YOUR_API_KEY" \
-H "Idempotency-Key: order_12345_payment" \
-H "Content-Type: application/json" \
-d '{"amount": 5000, "currency": "USD"}'How it works
- First request with key
abc123- Creates payment, returns result - Retry with same key
abc123- Returns cached result (no new payment) - Different key
xyz789- Creates new payment
Key requirements
| Requirement | Details |
|---|---|
| Uniqueness | Must be unique per operation |
| Length | Maximum 255 characters |
| Format | Any string (UUID recommended) |
| Expiry | Keys expire after 24 hours |
Generating keys
Use UUIDs or combine meaningful identifiers:
// UUID
const key = crypto.randomUUID();
// 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
// Meaningful identifier
const key = `order_${orderId}_payment_${Date.now()}`;
// 'order_12345_payment_1679529600000'When to use
Use idempotency keys for:
- Payment creation
- Refund creation
- Transfer creation
- Any operation that shouldn't be duplicated
Error handling
If you retry with the same key but different parameters:
{
"error": {
"type": "idempotency_error",
"code": "idempotency_key_in_use",
"message": "Keys for different request parameters must be unique."
}
}Best practices
- Generate unique keys - Use UUIDs or meaningful combinations
- Store keys - Save the key with your order for retry capability
- Don't reuse keys - Each operation needs a unique key
- Handle conflicts - If key conflict occurs, use a new key
Retry logic
async function createPaymentWithRetry(params, maxRetries = 3) {
const idempotencyKey = `payment_${params.orderId}_${Date.now()}`;
for (let i = 0; i < maxRetries; i++) {
try {
return await plexy.payments.create(params, { idempotencyKey });
} catch (error) {
if (error.statusCode >= 500 && i < maxRetries - 1) {
// Server error - safe to retry with same key
await sleep(Math.pow(2, i) * 1000);
continue;
}
throw error;
}
}
}