Integration Guide
Idempotency
Use Idempotency-Key to retry POST requests without creating duplicate records.
Money-moving endpoints are idempotent. The Idempotency-Key header is required on
POST /external/deposits and POST /external/withdrawals requests.
Idempotency-Key: 8c5e2c8a-7e3a-4b29-9c4f-3a1d8b1e9f00Idempotency lets you retry the same operation after a network failure. Pientegra uses the same tenant, API key, scope, and key combination to either replay the previous response or return a conflict.
How it works
| Scenario | Result |
|---|---|
| New key + new payload | The operation runs and the response is cached. |
| Same key + same payload | The first response is returned again. No duplicate record is created. |
| Same key + different payload | 409 idempotency_key_reuse_with_different_body. |
| Same key still in-flight | 409 duplicate_idempotency_key; retry later with the same key. |
| Pending row became stale | Pientegra may clear the old claim and run the operation again. |
The default TTL for idempotency records is 24 hours.
Key generation
- Generate a new UUID v4/v7 for each business operation.
- Store the key with the request payload in your own database.
- Reuse the same payload and same key when retrying.
- Do not use a user ID, order ID, or static string directly as the idempotency key.
const idempotencyKey = crypto.randomUUID();
await db.pientegraRequests.insert({
idempotencyKey,
payloadHash: sha256(JSON.stringify(payload)),
});
await fetch(`${apiBase}/external/withdrawals`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});const idempotencyKey = 'withdrawal'; // every request shares the same keyRetry pattern
async function postPientegra(path: string, payload: unknown, idempotencyKey: string) {
for (const delayMs of [0, 500, 1500, 4000, 10000]) {
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
const response = await fetch(`${process.env.PIENTEGRA_API_BASE}${path}`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PIENTEGRA_API_KEY!}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (response.ok) return await response.json();
const error = await response.json();
if (response.status >= 400 && response.status < 500 && response.status !== 429) {
throw new Error(`Pientegra ${error.error}: ${error.message}`);
}
}
throw new Error('Pientegra request failed after retries');
}Retry 429, 5xx, and network timeouts with the same key. 400, 401, 403,
and idempotency_key_reuse_with_different_body are permanent failures; fix the
request instead of retrying it.