A key aspect of Midaz’s reliability is making sure operations are safe to retry and never processed more than once.
Whether you're handling transactions or creating entities, your integration should be resilient, even when facing network hiccups, timeouts, or temporary disruptions. This page explains how Midaz protects against duplication using idempotency keys, and how you can implement them to handle retries in your system confidently.
Making retries safe
In real-world systems, failed API requests are common. Maybe a network timeout occurs. Maybe your service goes down right after sending a request. In these cases, it’s natural to retry, but how can you be sure Midaz won’t process the same operation twice?
That’s where idempotency keys come in.
By attaching a unique key to each request, you’re telling Midaz: "This is the same operation. If you’ve already processed it, don’t do it again."
Midaz stores this key temporarily and uses it to determine whether the request is new, already completed, or still being processed. This protects your system from duplicates while giving you full control over your retry strategy.
Idempotency in Midaz
Midaz uses idempotency keys to make sure operations are safe to retry, and never processed more than once. To do that, your request must include two headers:
X-Idempotency
: the unique key that identifies the request.X-TTL
: the time-to-live (in seconds) that Midaz should store this key in cache.
Here’s what happens behind the scenes:
- When a new key arrives, Midaz marks it as
pending
, processes the request, and stores the full response in cache. - If the same key is used again within the TTL window:
- If the operation is still running, Midaz returns a
409 Conflict
withX-Idempotency-Replayed: false
. - If it’s done, Midaz returns the exact same response, including headers and body, with
X-Idempotency-Replayed: true
.
- If the operation is still running, Midaz returns a
This model works across all Midaz endpoints and gives you a safe, predictable way to build retryable workflows, whether you're handling payments, background jobs, or high-volume transactions.
Workflow summary
Figure 1 shows the full lifecycle of an idempotent request:

Figure 1. Idempotent request lifecycle in Midaz.
How it works:
- If the request doesn’t include an existing idempotency key, Midaz creates a new one, processes the request, stores the response, and returns it with
X-Idempotency-Replayed: false
. - If the key already exists:
- If the operation is still running, Midaz returns a
409 Conflict
withX-Idempotency-Replayed: false
. - If the operation is complete, Midaz skips execution and returns the cached response with
X-Idempotency-Replayed: true
.
- If the operation is still running, Midaz returns a
This behavior ensures every request is handled safely, predictably, and without duplication, even when retried.
Example request
Here’s how to send an idempotent request to create a transaction:
POST /v1/transactions
X-Idempotency: 7fb8e1d098cd4730bb932d038b3b8651
X-TTL: 60
Content-Type: application/json
{
"amount": 1000,
"source": "wallet_A",
"destination": "wallet_B",
"asset": "USD"
}
If the request succeeds and you send it again within 60 seconds, Midaz will return the cached result with:
X-Idempotency-Replayed: true
If you send it again while the original is still being processed, you’ll receive a:
HTTP/1.1 409 Conflict
X-Idempotency-Replayed: false
Key generation
You generate the X-Idempotency
key on your side. The key should be deterministic, meaning if the same operation is retried, the key remains the same.
A simple and effective strategy is to create a hash based on the key fields that define the operation. For example:
- Transaction amount
- Source and destination
- Asset code
Here’s a quick example in Python:
import hashlib
def generate_idempotency_key(amount, source, destination, asset):
raw = f"{amount}:{source}:{destination}:{asset}".lower()
return hashlib.md5(raw.encode()).hexdigest()
Preventing entity duplication
For some endpoints, you don’t need idempotency keys to avoid duplication. Midaz enforces uniqueness constraints on critical resources like Accounts and Ledgers. If you attempt to create an entity with a name that already exists, the system blocks the request and returns a descriptive error.
This ensures that your data remains clean, unambiguous, and easy to manage, even when multiple services are operating in parallel or when retries occur automatically.
FAQ
What happens if I don’t send an idempotency key?
Midaz treats the request as new every time. This means retries may result in duplicated operations.
Can I reuse a key across endpoints?
No. Keys should be scoped to a single operation and endpoint.
What happens if I change the TTL on a retry?
Only the TTL from the first request is used. Changing it later has no effect.
Will the replayed response always be identical?
Yes. Midaz replays the full response, including headers and body, for completed requests.
What’s the default TTL if I don’t send X-TTL?
The default window is 300 seconds (5 minutes), but you can customize it up to your allowed limit per endpoint.