Idempotency
Every creation endpoint (POST /invoices, POST /payouts, POST .../refunds) requires an Idempotency-Key header. Send the same key on a retry and you get the exact original response back. No second resource is created, no double charge happens.
The header
| Header | Required on | Format | Max length |
|---|---|---|---|
Idempotency-Key | All POST creation endpoints | Any string; UUID v4 recommended | 128 characters |
Missing key → 400 IDEMPOTENCY_REQUIRED. Empty string → same.
Retention window
The key + cached response are stored for 24 hours after the original successful request. After that window the key is expired. Sending the same key creates a new resource as if the key were fresh.
Replay behaviour
- Same key + same body → HTTP status and body are replayed byte-for-byte from the cache.
- Retries with the same key return the stored response directly, without re-processing the request.
- One-time secrets embedded in the original response (e.g. a payment link token) are also replayed, so the caller doesn’t lose them on a retry.
Conflict: same key, different body
If you send the same Idempotency-Key with a different request body, the server returns 422 IDEMPOTENCY_KEY_REUSED_DIFFERENT_BODY. Generate a new UUID for the new request.
json
{
"error": {
"code": "IDEMPOTENCY_KEY_REUSED_DIFFERENT_BODY",
"message": "same Idempotency-Key sent with a different request body",
"request_id": "..."
}
}Missing key
json
{
"error": {
"code": "IDEMPOTENCY_REQUIRED",
"message": "Idempotency-Key header is required for invoice creation",
"request_id": "..."
}
}Code samples
Node.js
javascript
import crypto from 'node:crypto';
const idempotencyKey = crypto.randomUUID(); // UUID v4
const res = await fetch('https://swapss.lol/api/v1/merchant/invoices', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: '5.00',
currency: 'USDT',
chain: 'tron',
order_id: 'ORD-1042',
}),
});
const invoice = await res.json();Python
python
import uuid
import requests
idempotency_key = str(uuid.uuid4())
resp = requests.post(
"https://swapss.lol/api/v1/merchant/invoices",
headers={
"Authorization": f"Bearer {api_key}",
"Idempotency-Key": idempotency_key,
"Content-Type": "application/json",
},
json={
"amount": "5.00",
"currency": "USDT",
"chain": "tron",
"order_id": "ORD-1042",
},
timeout=30,
)
invoice = resp.json()PHP
php
<?php
use Ramsey\Uuid\Uuid;
$idempotencyKey = Uuid::uuid4()->toString();
$response = $httpClient->post('https://swapss.lol/api/v1/merchant/invoices', [
'headers' => [
'Authorization' => "Bearer {$apiKey}",
'Idempotency-Key' => $idempotencyKey,
'Content-Type' => 'application/json',
],
'json' => [
'amount' => '5.00',
'currency' => 'USDT',
'chain' => 'tron',
'order_id' => 'ORD-1042',
],
]);
$invoice = json_decode($response->getBody(), true);Best practices
- Generate one UUID per business attempt. If your job framework retries a task, reuse the same key across those retries. That’s the whole point.
- Store the key alongside the order in your database before sending the request. If your process crashes, the stored key lets you safely retry.
- Do not share keys across different operations (e.g. don’t reuse an invoice key for a payout). Each resource type has its own idempotency namespace.