Skip to main content
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

ScenarioResult
Same key + same body, within 24 hoursYuno returns the original stored response without re-executing the operation
Same key + different bodyOnly the first request is processed; subsequent requests with a different body return the original response
Same key sent concurrentlyThe second in-flight request receives a 409 Conflict response
Request results in a 400 errorThe key is not stored; safe to fix the request and retry with the same key
Request results in a 500 errorThe 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.