Contact
Home / Insights / Payments engineering

Payments engineering

Payment webhooks: knowing what happened after a timeout

A request can time out while a payment continues elsewhere. A provider can send the same update twice. The engineering problem is keeping a clear account of the transaction while different systems report what they know.

For payment product owners and engineers designing an understandable transaction lifecycle.

The useful starting point

Treat a payment as a lifecycle, not a single API response. Define which updates can change its state, how repeated work is handled and how uncertain outcomes are investigated.

A timeout: a worked example

Imagine a request leaving your service and the connection closing before the response arrives. The application knows that it did not receive an answer. It may not yet know whether the outside system accepted the request.

Automatically telling the customer to pay again can turn uncertainty into a second problem. A workflow needs an explicit way to represent the unresolved state and check what happened before deciding the next action.

Trace one transaction through uncertainty

Illustrative example · a simplified lifecycle, not a client’s state model or an incident report

One possible transaction lifecycle
  1. 1Request recorded with a reference
  2. 2Provider outcome is still uncertain
  3. 3Authoritative result is confirmed
  4. 4Records are checked and the outcome is visible
A constructed transaction timeline
ObservationWhat the application actually knowsHandling to define
A request is recorded as TX-DEMO-01There is one intended operation with a referenceKeep a way to correlate internal work and outside requests
The connection times outA response was not received; acceptance may be unresolvedRepresent uncertainty and check the original operation before retrying movement
A completion update arrivesThe provider reports a result for that operationValidate and correlate the update before applying the permitted transition
The same event arrives againThere is another delivery of previously handled informationAvoid repeating the business effect; retain enough history to explain the delivery
An older processing update arrives lateArrival time alone does not establish the latest stateUse the agreed transition rules and authoritative information

The important distinction is between another attempt to deliver information and another intended payment. Give both concepts explicit identities. Otherwise an application can confuse repeated communication with new work.

Separate three responsibilities

Request identity

Decide how an intended operation is identified and how a retry relates to it. An event identifier from one provider may help detect repeated delivery, but it is not automatically the identifier of the whole business operation.

State authority

Define which source can establish a result and which transitions are allowed. A completion label should reflect the product’s actual meaning of completion, including the relevant provider contract.

Operational explanation

Give the team a way to inspect the references, meaningful updates and unresolved questions. That view helps distinguish a missing message, an uncertain provider outcome and a mismatch between records.

Use a failure-focused acceptance checklist

Alongside the ordinary journey, exercise repeated delivery, a missing response, a late update and recovery after interrupted processing. Check both the resulting state and the operational explanation.

Passing one duplicate-event test is not proof that every possible financial effect is protected. Identify which action must not repeat, where its identity is retained and how a recovery can establish what already happened. That is more useful than attaching a broad reliability label to the integration.

Repeated messages need predictable handling

A webhook is an update sent from another system to your application. Delivery can be retried, so handling an update twice must not blindly repeat a financial action.

Idempotency is the property that repeating a request does not create an additional effect. The important design question is what identifies the operation being repeated and where the system records that it has already been handled. A duplicate event and a separate legitimate payment must remain distinguishable.

Arrival order is not the whole transaction history

Different messages may describe different stages of the same operation. A late update should not automatically overwrite a later, authoritative state merely because it arrived last.

Write down the permitted transitions and which source can establish each one. Where provider information conflicts or remains incomplete, define how the transaction is checked and who can see that uncertainty. The exact state model depends on the provider contract and the product.

Make investigation part of the product

A useful operational view should connect the internal transaction reference to relevant external references and the history of meaningful changes. That gives the team a starting point for tracing a payment without relying on a customer-facing label alone.

  • What identifies the original operation?
  • What happens if the same request or update arrives again?
  • Can a late message move a completed transaction backwards?
  • How is an uncertain result checked?
  • Which information is available to the person resolving it?

The systems behind our payments work

Codek’s wider payments work includes banking and payout integrations with provider webhooks, consumer apps, business tools, ledger and reconciliation components. Our role spans the services that handle a transaction and the interfaces through which users and operators understand it.

Those responsibilities make correlation and state clarity useful engineering questions, rather than just API integration details. The payments case shows the product scope and continuing engagement. The timeline above is a constructed example used to explain the problem, not a reconstruction of a private transaction.

For a documented provider example of retries, duplicate events and ordering, see Stripe’s webhook documentation (opens in a new tab). The reference illustrates delivery behaviour without identifying any client’s providers.

Common questions

Does an idempotency key solve every duplicate payment problem?

It solves a defined repetition problem only within the behaviour and lifetime of the system using it. Request identity, callback handling, state transitions and recovery still need to be considered across the full workflow.

Can we mark a payment failed after an API timeout?

A missing response is not necessarily a final payment outcome. Define how the original operation is checked and how uncertainty is represented according to the integration’s contract.

Keep exploring

All insights

Engineering operations

A notification was sent. Does the user know what happened?

A service can accept a message without proving that a person saw it. Notifications are an important part of the experience, but the product still needs an authoritative place to show what happened.

5 min read