← Back to Blog
Engineering26.01.2026·4 min read

Payment API Idempotency: Why It Matters for Crypto Transactions

A network timeout, a client retry, a load balancer hiccup — and suddenly your customer is charged twice for the same order. In crypto, there is no chargeback to fix it. Idempotency is the engineering discipline that prevents this.

Quick Answer

Idempotency means that making the same API request multiple times produces the same result as making it once. For a payment API, this ensures that if a network error causes your client to retry a charge request, the customer is only charged once.

Picture a common scenario: a customer clicks “Pay Now,” your frontend sends a POST request to the payment API, and the connection drops before the response arrives. Your client retries automatically. Without idempotency, the payment processor treats this as two separate requests and initiates two blockchain transactions. The customer's wallet is debited twice. In traditional payments, you could reverse the duplicate with a chargeback or void. With crypto, once the transaction is confirmed on-chain, it is permanently irreversible. Industry data shows that 3–5% of all payment API calls are retries, and the average cost of a duplicate crypto payment that reaches the blockchain is approximately $2,500 when you factor in the payment amount, recovery coordination, and customer support overhead.

What Idempotency Means for Payment APIs

Idempotency is a property of an API operation where making the same request multiple times produces the same result as making it once. For a payment API, this means that if you send the same charge request three times due to retries, the customer is only charged once. The first request creates the payment. The second and third requests recognise the duplicate and return the original response without creating new transactions.

HTTP GET requests are naturally idempotent — fetching the same resource multiple times has no side effects. But POST requests, which payment APIs use to create charges, are not idempotent by default. Each POST is treated as a new operation. Idempotency keys solve this by giving the server a way to recognise that a POST request is a retry of a previous request rather than a new one.

Why Crypto Makes Idempotency Non-Negotiable

In traditional payments, duplicate charges are an inconvenience. In crypto payments, they are a crisis. The fundamental difference is reversibility. A credit card processor can void or refund a duplicate charge within seconds. A crypto payment, once broadcast to the network and included in a block, cannot be reversed without the recipient voluntarily sending the funds back. On networks with fast confirmation times, a duplicate transaction can be finalised before anyone notices.

This irreversibility compounds in several ways. First, the merchant must identify the duplicate, which requires reconciliation against the blockchain — a more complex process than querying a card processor's API. Second, recovering funds requires contacting the customer and coordinating a return transaction, which incurs its own gas fees. Third, the customer experience suffers: seeing a double charge in a crypto wallet creates immediate distrust, and the resolution timeline is days rather than minutes.

How Idempotency Keys Work

The mechanism is straightforward. When your client makes a payment API request, it generates a unique key — typically a UUID v4 — and includes it in the request header. The server uses this key to track whether it has seen this request before.

  • First request. The server checks its idempotency store for the key. Not found. It processes the request, creates the payment, stores the key along with the response, and returns the result.
  • Retry request (same key). The server finds the key in its store. It returns the stored response without executing any payment logic. The client receives the same response as the first call.
  • New request (different key). The server does not find the key. It treats this as a new payment and processes it normally.

The key insight is that the client controls deduplication. Only the client knows whether a request is a retry or a genuinely new operation. By generating the key before the first attempt and reusing it on retries, the client ensures that network failures never translate into duplicate payments.

UUID v4: The Standard Key Format

UUID v4 is the industry standard for idempotency keys. Each UUID v4 is a 128-bit random value, formatted as a 36-character string like 550e8400-e29b-41d4-a716-446655440000. The probability of two independently generated UUIDs colliding is approximately 1 in 5.3 billion billion — effectively zero for any practical volume of API calls.

Some developers use composite keys derived from business logic, such as a hash of the order ID, amount, and customer ID. While this can work, it introduces risks: if any of those values change between retries (for example, a price update), the key changes and deduplication fails. UUID v4 avoids this entirely because the key is generated once and reused verbatim.

Server-Side Deduplication Architecture

On the server side, the payment processor must store idempotency keys in a fast, highly available data store. The lookup must happen before any payment logic executes — including before any blockchain transaction is broadcast. A typical architecture uses Redis or a similar in-memory store for key lookups, with the following flow.

  • Atomic check-and-set. Use a compare-and-swap or SET NX (set if not exists) operation to atomically claim the key. This prevents race conditions where two concurrent requests with the same key both pass the existence check.
  • In-flight locking. While the first request is being processed, subsequent requests with the same key should receive a 409 Conflict or wait with a brief backoff. This handles the case where a retry arrives while the original request is still executing.
  • Response caching. Once processing completes, the full response (including status code, headers, and body) is stored alongside the key. Subsequent lookups return this cached response exactly.
  • Body mismatch detection. Some implementations also store a hash of the request body. If a request arrives with the same key but a different body, the server returns a 422 Unprocessable Entity error, alerting the client that the key is being misused.

TTL: When Keys Expire

Idempotency keys cannot be stored forever. Unbounded storage would grow linearly with transaction volume, and ancient keys serve no practical purpose. Most payment APIs set a TTL (time to live) of 24 to 48 hours. This window is long enough to cover retry storms, delayed client-side retries, and incident recovery scenarios where a client replays requests after an outage. After the TTL expires, the key is purged. If a request arrives with an expired key, it is treated as a new operation.

The TTL should align with your retry policy. If your client retries with exponential backoff over a maximum of 24 hours, the TTL should be at least 24 hours plus a buffer. SpacePay uses a 48-hour TTL by default, configurable per merchant for specific use cases.

Common Failure Scenarios

Understanding when retries occur helps you appreciate why idempotency is not a nice-to-have but a hard requirement.

ScenarioCauseWithout IdempotencyWith Idempotency
Network timeoutResponse lost in transitDuplicate paymentOriginal response returned
Load balancer restartConnection dropped mid-requestDuplicate paymentSafely deduplicated
Client crash and restartApp restarts and replays pendingDuplicate paymentSafely deduplicated
Double-clickUser clicks pay button twiceDuplicate paymentSecond click ignored
DNS resolution delayClient retries before DNS resolvesDuplicate paymentSafely deduplicated

Implementation Best Practices

Whether you are building an integration with SpacePay or designing your own payment service, these practices ensure idempotency works reliably in production.

  • Generate keys before the first attempt. Create the UUID before sending the request and persist it until you receive a definitive response. If the request fails, reuse the same key on retry.
  • Never reuse keys across different operations. Each unique payment intent should have its own idempotency key. A new order gets a new key, even if the amount and customer are the same.
  • Handle 409 Conflict responses. If the server returns a 409, it means your request is being processed from a previous attempt. Wait briefly and retry, or fetch the payment status via a GET endpoint.
  • Log idempotency keys. Include the key in your application logs alongside the order ID. This makes debugging duplicate payment reports straightforward — you can trace exactly which requests shared a key and what the server returned for each.
  • Combine with webhook notifications. Idempotency prevents duplicate creation. Webhooks confirm the outcome. Together they form a complete, reliable payment flow where no event is missed and no payment is duplicated.

Frequently Asked Questions

What is idempotency in the context of a payment API?

Idempotency means that making the same API request multiple times produces the same result as making it once. For payments, this guarantees that retries caused by network errors never result in duplicate charges. The API uses a unique key provided by the client to recognise and deduplicate repeated requests.

Why is idempotency especially important for crypto payments?

Crypto transactions are irreversible once confirmed on the blockchain. Unlike credit card payments, there is no chargeback mechanism. If a duplicate API call creates a second blockchain transaction, recovering those funds requires the recipient to voluntarily return them — a process that is slow, uncertain, and costly.

What percentage of API calls are retries?

Industry data indicates that 3 to 5 percent of payment API calls are retries caused by network timeouts, client-side errors, or infrastructure interruptions. At scale, even this modest percentage translates to thousands of potential duplicate payments per month without idempotency protection.

How long should idempotency keys be stored?

Most payment APIs retain keys for 24 to 48 hours. This covers retry storms, delayed client retries, and incident recovery. After the TTL expires, the key is purged. SpacePay defaults to 48 hours, configurable per merchant.

Should the client or server generate the idempotency key?

Always the client. The client is the only party that knows whether a request is a retry or a new operation. Generating the key client-side and reusing it on retries is the only way to ensure proper deduplication without additional round trips.

What happens if two different payments use the same key?

The second payment would receive the first payment's response, effectively blocking it. Using UUID v4 makes accidental collisions statistically impossible. Some APIs additionally verify that the request body matches and return a 422 error if the key is reused with different parameters, catching developer mistakes early.

What is the average cost of a duplicate crypto payment?

Approximately $2,500 per incident when accounting for the payment amount, recovery coordination, gas fees for return transactions, and customer support overhead. This does not include indirect costs like reputational damage and customer churn, which can be substantially higher for businesses with repeat customers.

Conclusion

Idempotency is not an advanced feature — it is a baseline requirement for any payment API, and doubly so for crypto where transactions cannot be reversed. The pattern is well understood: UUID v4 keys generated by the client, atomic server-side deduplication, a sensible TTL, and clear error responses for edge cases. With 3–5% of API calls being retries and each duplicate costing an average of $2,500, the return on implementing idempotency correctly is immediate and measurable. Every SpacePay API endpoint is idempotent by design, so your integration is protected from the first request.