Idempotency keys
Idempotency ensures that an API request, if retried due to a network error or timeout, won’t accidentally be performed multiple times. This is crucial for operations like creating payments or refunds to prevent duplicate actions.
How it works
When you make a potentially mutating API request (like POST
, PATCH
, DELETE
), you can include a unique Idempotency-Key
in the request header.
- Generate a Unique Key: Create a unique string (e.g., a UUID) for each distinct operation you want to perform. This key represents the intent to perform the operation.
- Include the Header: Send the key in the
Idempotency-Key
header with your request. - First Request: lomi. processes the request normally and stores the result associated with your key.
- Subsequent Requests (Same Key): If lomi. receives another request with the same key within 24 hours, it will not re-process the operation. Instead, it will return the same response (success or error) that it sent for the original request.
Using idempotency keys
Include the Idempotency-Key
header in your API calls. Most lomi. SDKs provide a way to pass this easily.
import { LomiSDK } from '@lomi/sdk';
import { v4 as uuidv4 } from 'uuid';
const lomi = new LomiSDK({ apiKey: process.env.LOMI_API_KEY! });
// Generate a unique key *before* making the request
const idempotencyKey = uuidv4(); // e.g., 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
try {
const session = await lomi.checkoutSessions.create({
merchant_id: 'your_merchant_id',
amount: 1000,
currency_code: 'XOF',
allowed_providers: ['WAVE'],
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/cancel',
// ... other params
}, {
// Pass the key in the request options
idempotencyKey: idempotencyKey
});
console.log('Checkout session created/retrieved:', session.data.checkout_session_id);
// Store the key and the result (session ID) associated with your operation
} catch (error) {
console.error('Failed to create checkout session:', error);
// Handle the error
}
import { v4 as uuidv4 } from 'uuid';
const idempotencyKey = uuidv4();
const apiKey = process.env.LOMI_API_KEY;
const apiUrl = 'https://api.lomi.africa/v1/checkout-sessions'; // Use correct endpoint
async function createSessionDirectly() {
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
merchant_id: 'your_merchant_id',
amount: 1000,
currency_code: 'XOF',
allowed_providers: ['WAVE'],
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/cancel',
// ... other params
})
});
const data = await response.json();
if (!response.ok) {
// Handle API error (response.status, data.error)
console.error(`API Error (${response.status}):`, data.error);
return;
}
console.log('Checkout session created/retrieved:', data.data.checkout_session_id);
} catch (networkError) {
console.error('Network error during request:', networkError);
// Implement retry logic here if appropriate, reusing the SAME idempotencyKey
}
}
createSessionDirectly();
Generating keys
Keys must be unique for each distinct operation.
- UUIDs: Recommended approach. Generate a standard UUID v4 for each request attempt.
import { v4 as uuidv4 } from 'uuid'; const key = uuidv4();
- Deterministic Keys: You can create keys based on unique aspects of the operation (e.g., user ID + order ID + timestamp), but ensure the resulting key is truly unique for each intended operation. Be cautious about collisions.
Key lifecycle
- lomi. stores idempotency keys and their corresponding responses for 24 hours.
- After 24 hours, a key expires and can potentially be reused, although using unique keys like UUIDs is generally safer.
- Sending a request with a key that was used within the last 24 hours for a different request body might result in an error.
Error handling
If you retry a request with an idempotency key that was already successfully processed, you’ll receive the original successful response (HTTP 200 OK
).
If the original request failed (e.g., HTTP 400 Bad Request
), retrying with the same key will return the original error response. You won’t be able to fix the request by simply retrying with the same key.
Specific idempotency-related errors (though less common if using UUIDs correctly):
409 Conflict
(or similar): Might occur if you attempt to reuse a key with different request parameters than the original request within the 24-hour window.
Best practices
- Use for Mutating Requests: Primarily use idempotency keys for
POST
,PATCH
, andDELETE
requests where duplicate operations could cause issues. - Generate Keys Correctly: Use a robust method like UUID v4 to ensure uniqueness for each operation attempt.
- Retry Network Errors: When a request fails due to a network error or timeout (where you don’t receive a definitive success or failure from lomi.), retry the request using the exact same idempotency key.
- Don’t Retry Client Errors: Do not retry requests that failed with a
4xx
status code (other than potentially429 Rate Limit Exceeded
) using the same idempotency key. Fix the underlying issue in the request first and generate a new key for the corrected request. - Store Keys (Optional): You might store the idempotency key alongside your internal record of the operation (e.g., in your order database) to aid in tracking and debugging retries.
Common scenarios
- Creating Payments/Checkout Sessions: Essential to prevent charging a customer twice if your initial request times out but was actually processed by lomi..
- Creating Refunds: Prevents accidentally refunding a transaction multiple times.
- Creating Customers/Products/Webhooks: Useful to avoid creating duplicate resources due to retries.