Optional analytics on public pages. No session recording. Support works either way. Privacy details
API reference
Retry any POST safely. The same key and body never create anything twice.
Send Idempotency-Key on every POST: a UUID or a stable value per attempt such as order-1048-attempt-1, up to 255 characters. Keys are scoped to your organization and environment. If a request times out, retry with the same key and the same body.
const response = await fetch(`${process.env.BOSPAY_API_BASE}/invoices`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"BOSPay-Version": "2026-09-23",
"X-API-Key": process.env.BOSPAY_API_KEY,
"Idempotency-Key": "order-1048-attempt-1",
},
body: JSON.stringify({
"fiatAmount": 150,
"fiatCurrency": "ZAR",
"tokenSymbol": "USDC",
"chain": "sepolia",
"metadata": {
"orderId": "1048"
}
})
});
if (!response.ok) {
throw new Error(`BOSPay request failed: ${response.status}`);
}
const data = await response.json();| Situation | Result |
|---|---|
| First request | Runs normally. A successful response is stored for 24 hours. |
| Retry, same key and body | The stored response, with Idempotent-Replayed: true. Nothing is created twice. |
| Same key, different body or endpoint | 409 idempotency_conflict. Use a new key for a new request. |
| Retry while the first is still running | 409 idempotency_in_progress. Retry shortly with the same key. |
| First request was rejected (any 4xx) | Nothing happened, so the key is released. Fix the request and retry with the same key. |
| First request failed with 5xx or the connection dropped | Invoice creation, invoice cancel, checkout sessions, realtime tokens and refunds: retrying with the same key finishes the same operation. Other requests: 409 operation_uncertain until an admin resolves it. |
A 5xx or timeout does not prove the request did nothing. Requests that can finish safely on retry do so: POST /invoices stores its quote (amount, rate, expiry, payout wallet) under the key before calling the settlement rail, so a retry after a crash returns the same invoice with the same amount and payment address, and BOSPay finishes interrupted invoices on its own every 15 seconds. For other requests the key answers 409 operation_uncertain instead of running again.
On operation_uncertain, check whether the object exists (for example the webhook endpoint or metadata you sent). An organization admin then resolves it in the console under Security → Needs review: "did not happen" releases the key so your retry runs; "did happen" makes retries return a 409 explaining that. Every decision is kept in the audit log. Do not switch to a new key to get past it; that is how duplicates happen.