When network failures or timeouts occur, it is tempting to simply retry a failed request. Without idempotency, that retry could trigger a duplicate payment. Idempotency guarantees that sending the same request multiple times produces exactly the same result as sending it once — no duplicate charges, no double captures.
How idempotency works
Yuno uses the X-Idempotency-Key header to track requests. When you include a unique key with a request, Yuno stores the result of that operation. If you send the same key again, Yuno returns the stored response instead of executing the operation a second time.
The key must be a UUID v4 string that you generate on the client side. You are responsible for generating a fresh key for each new logical operation and reusing that same key only when retrying that specific operation.
X-Idempotency-Key is required on Create Payment requests. It is strongly recommended on all other POST requests as a reliability best practice.
Idempotency behavior reference
| Scenario | Result |
|---|
| Same key + same body, within 24 hours | Yuno returns the original stored response without re-executing the operation |
| Same key + different body | Only the first request is processed; subsequent requests with a different body return the original response |
| Same key sent concurrently | The second in-flight request receives a 409 Conflict response |
Request results in a 400 error | The key is not stored; safe to fix the request and retry with the same key |
Request results in a 500 error | The key is not stored; safe to retry with the same key |
If you receive an IDEMPOTENCY_DUPLICATED error code, it means the key was already used for a successfully processed operation. Generate a new UUID before retrying if you intend to create a new resource.
Generating idempotency keys
Node.js
import { v4 as uuidv4 } from 'uuid';
const idempotencyKey = uuidv4();
const response = await fetch('https://api-sandbox.y.uno/v1/payments', {
method: 'POST',
headers: {
'public-api-key': process.env.YUNO_PUBLIC_API_KEY,
'private-secret-key': process.env.YUNO_PRIVATE_SECRET_KEY,
'account-code': process.env.YUNO_ACCOUNT_CODE,
'X-Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(paymentPayload),
});
if (!response.ok) {
const error = await response.json();
// If status is 500 or 504, safe to retry with the same idempotencyKey
console.error('Payment failed:', error.code, error.messages);
}
Python
import uuid
import httpx
idempotency_key = str(uuid.uuid4())
response = httpx.post(
"https://api-sandbox.y.uno/v1/payments",
headers={
"public-api-key": YUNO_PUBLIC_API_KEY,
"private-secret-key": YUNO_PRIVATE_SECRET_KEY,
"account-code": YUNO_ACCOUNT_CODE,
"X-Idempotency-Key": idempotency_key,
"Content-Type": "application/json",
},
json=payment_payload,
)
if response.status_code not in (200, 201):
error = response.json()
# 400 errors do not consume the key — fix the payload and retry
print(f"Error: {error['code']} — {error['messages']}")
Key lifetime and storage
Idempotency keys are stored by Yuno for 24 hours from the time of the first successful request. After 24 hours, the key expires and a request with that key is treated as a new operation.
Store the key alongside your pending transaction record in your own database. If a response is never received (network timeout), look up the stored key and use it to retry — you will receive the original response if the request reached Yuno successfully, or trigger processing if it did not.