Key points of this lesson, in order.
Idempotency in depth: keys, replay, conflict and storage
What you will learn
Your objective. By the end of this lesson, you will be able to explain idempotency in depth: keys, replay, conflict and storage and apply it to a real banking scenario.
Why it matters. For a business analyst, the requirement is to define the key format, the header name, the storage duration, the replay behaviour, the conflict response, and the scoping rule, and to test each with a real retry.
Chapter objective: How payment APIs are designed, versioned, secured and integrated
Key learning points
- Idempotency and safe retries
- Seen-key check
- Client-scoped keys
- Idempotency testing
- UUID version 4 keys
- New key, new payment
Key terms
Reconciliation: The process of comparing records from two sources, such as a bank statement and an internal ledger, to confirm they agree.
Idempotency: The property that repeating the same request has the same effect as sending it once. In payments, an idempotency key lets a client safely retry a request after a timeout without creating a duplicate...
Return: A payment that is sent back to the sender after settlement because it cannot be credited to the beneficiary.
Payment flow diagram showing Idempotency in depth: keys, replay, conflict and storage.
Practise this lesson
Exercise
Write the request and the expected response for the API call described in this lesson.
Use the API resources, operations and fields named in this lesson.
- What to do. Write the JSON request with the required fields, the success response, and one error response with its error code.
Correct result. A correct request has all mandatory fields, a valid idempotency key, and the right resource and operation. The success response confirms acceptance, and the error response names the field or rule that failed.
Why. An API contract is a promise between two systems. If the request is wrong, the API must reject it cleanly, not fail silently.
Check your understanding
Practice question
Which of the following best describes idempotency in depth: keys, replay, conflict and storage?
Takeaway and next step
What to remember
The bank stores the key together with the request body and the response.
Follow a payment through every stage, from instruction to beneficiary credit, and note where it can stop.
Open the Payment Lifecycle Simulator →
Builds on "Error taxonomy: HTTP status is not the payment status".
Transcript and full text
Show transcript
Idempotency is the property that lets a client safely retry a request without creating a duplicate payment. When a client sends a payment instruction and receives no response, because the network timed out or the bank's system was slow, it does not know whether the payment was created. Without idempotency, the only safe action is to enquire about the payment status and wait, which is slow and complex. With idempotency, the client simply resends the same request with the same idempotency key, and the bank returns the original response instead of creating a second payment. Every POST that changes something in a payment API must require an idempotency key. Source: API design guidance; bank API developer documentation; IETF draft on idempotency keys. An idempotency key is a unique value the client generates for each distinct payment instruction, typically a UUID. The client sends it in a header, usually Idempotency-Key, with the request. The bank stores the key together with the request body and the response. When a request arrives, the bank checks whether it has seen the key before. If it has not, it processes the request, stores the key with the body and the response, and returns the response. If it has seen the key before, it compares the new request body with the stored body. If they are identical, it returns the stored response without processing again: this is a replay, and it is safe. If they differ, it returns a 409 Conflict with a code such as IDEMPOTENCY_KEY_REUSED, because the same key with a different body is either a client error or an attempt to reuse a key fraudulently. For a business analyst, the requirement is to define this behaviour in the API specification, because the client builds against the specification and nothing else. The storage of idempotency keys has rules. A key must be stored for at least as long as a client might reasonably retry, typically 24 hours for a payment API, and often longer. A key must be stored atomically with the payment record, so that a crash cannot leave a payment created but its key unrecorded, which would allow a retry to create a duplicate. A key is scoped to the client that created it: two different clients may use the same key value without conflict, because the bank stores the key together with the client identifier. A key must never be reused for a different payment, even after the original has completed, because a late retry of the original would then return the response for the wrong payment. For a business analyst, the requirement is to define the key format, the header name, the storage duration, the replay behaviour, the conflict response, and the scoping rule, and to test each with a real retry. The API documentation must state this rule plainly, because a client that has to guess will guess wrong. The failure mode that idempotency does not solve is the ambiguous outcome. If the bank's system crashes after creating the payment but before storing the idempotency key, a retry will create a duplicate, because the bank has no record of the first request. The defence is to store the key and the payment in the same database transaction, so they are either both recorded or neither is. A test pack that does not cover this case will pass in the test environment and fail when a real client calls the API. A second failure mode is a client that generates a new key for every retry, perhaps because it generates the key from a timestamp. Each retry then looks like a new payment, and the bank creates a duplicate for each one. The defence is documentation and testing: the API documentation must state clearly that the client must reuse the same key for retries, and the bank's test pack must include a test that retries with the same key and verifies only one payment is created. The idempotency key must be generated by the client, not by the bank, because only the client knows whether a request is a retry of an earlier request or a new request. If the bank generated the key, it would generate a different key for each retry, and each retry would look like a new payment. The client generates the key when it first creates the payment instruction, stores it with the instruction, and reuses it for every retry of that instruction. A common pattern is to use a UUID version 4, which is random and unique enough that two clients will not generate the same key by chance. The key must be sent in the Idempotency-Key header with every POST that changes something, and the bank must reject a POST that does not carry a key with a 400 error and a code such as MISSING_IDEMPOTENCY_KEY, so the client knows it must supply one. The error response must carry this information, because a client that cannot diagnose the failure cannot fix it. Idempotency and the payment identifier are different things and must not be confused. The idempotency key identifies a request: it tells the bank whether this request has been seen before. The payment identifier identifies a payment: it is the unique value the bank assigns to the payment once it is created, and it appears in every status update, investigation and reconciliation entry for that payment. A client that retries a payment instruction with the same idempotency key receives the same payment identifier back, because it is the same payment. A client that sends a new payment instruction with a new idempotency key receives a new payment identifier, because it is a different payment. For a business analyst, the requirement is to define the idempotency key format, the header, the storage duration, and the relationship between the key and the payment identifier, and to test that a retry returns the original payment identifier. Further reading: API design guidance; IETF draft on idempotency keys. Last reviewed 7 November 2026.
Idempotency is the property that lets a client safely retry a request without creating a duplicate payment. When a client sends a payment instruction and receives no response, because the network timed out or the bank's system was slow, it does not know whether the payment was created. Without idempotency, the only safe action is to enquire about the payment status and wait, which is slow and complex. With idempotency, the client simply resends the same request with the same idempotency key, and the bank returns the original response instead of creating a second payment. Every POST that changes something in a payment API must require an idempotency key. Source: API design guidance; bank API developer documentation; IETF draft on idempotency keys.
An idempotency key is a unique value the client generates for each distinct payment instruction, typically a UUID. The client sends it in a header, usually Idempotency-Key, with the request. The bank stores the key together with the request body and the response. When a request arrives, the bank checks whether it has seen the key before. If it has not, it processes the request, stores the key with the body and the response, and returns the response.
If it has seen the key before, it compares the new request body with the stored body. If they are identical, it returns the stored response without processing again: this is a replay, and it is safe. If they differ, it returns a 409 Conflict with a code such as IDEMPOTENCY_KEY_REUSED, because the same key with a different body is either a client error or an attempt to reuse a key fraudulently. For a business analyst, the requirement is to define this behaviour in the API specification, because the client builds against the specification and nothing else.
The storage of idempotency keys has rules. A key must be stored for at least as long as a client might reasonably retry, typically 24 hours for a payment API, and often longer. A key must be stored atomically with the payment record, so that a crash cannot leave a payment created but its key unrecorded, which would allow a retry to create a duplicate. A key is scoped to the client that created it: two different clients may use the same key value without conflict, because the bank stores the key together with the client identifier.
A key must never be reused for a different payment, even after the original has completed, because a late retry of the original would then return the response for the wrong payment. For a business analyst, the requirement is to define the key format, the header name, the storage duration, the replay behaviour, the conflict response, and the scoping rule, and to test each with a real retry. The API documentation must state this rule plainly, because a client that has to guess will guess wrong.
The failure mode that idempotency does not solve is the ambiguous outcome. If the bank's system crashes after creating the payment but before storing the idempotency key, a retry will create a duplicate, because the bank has no record of the first request. The defence is to store the key and the payment in the same database transaction, so they are either both recorded or neither is. A test pack that does not cover this case will pass in the test environment and fail when a real client calls the API.
A second failure mode is a client that generates a new key for every retry, perhaps because it generates the key from a timestamp. Each retry then looks like a new payment, and the bank creates a duplicate for each one. The defence is documentation and testing: the API documentation must state clearly that the client must reuse the same key for retries, and the bank's test pack must include a test that retries with the same key and verifies only one payment is created.
The idempotency key must be generated by the client, not by the bank, because only the client knows whether a request is a retry of an earlier request or a new request. If the bank generated the key, it would generate a different key for each retry, and each retry would look like a new payment. The client generates the key when it first creates the payment instruction, stores it with the instruction, and reuses it for every retry of that instruction.
A common pattern is to use a UUID version 4, which is random and unique enough that two clients will not generate the same key by chance. The key must be sent in the Idempotency-Key header with every POST that changes something, and the bank must reject a POST that does not carry a key with a 400 error and a code such as MISSING_IDEMPOTENCY_KEY, so the client knows it must supply one. The error response must carry this information, because a client that cannot diagnose the failure cannot fix it.
Idempotency and the payment identifier are different things and must not be confused. The idempotency key identifies a request: it tells the bank whether this request has been seen before. The payment identifier identifies a payment: it is the unique value the bank assigns to the payment once it is created, and it appears in every status update, investigation and reconciliation entry for that payment. A client that retries a payment instruction with the same idempotency key receives the same payment identifier back, because it is the same payment.
A client that sends a new payment instruction with a new idempotency key receives a new payment identifier, because it is a different payment. For a business analyst, the requirement is to define the idempotency key format, the header, the storage duration, and the relationship between the key and the payment identifier, and to test that a retry returns the original payment identifier. Further reading: API design guidance; IETF draft on idempotency keys. Last reviewed 7 November 2026.
Full lesson text (all scenes)
Completing a lesson updates your progress dashboard on the homepage.
Scene timestamps are estimated by allocating the narration text proportionally across the real audio length. The audio playback position is the source of truth: pause freezes the visual, seeking restores the correct scene, replay restarts the scene animation.