When a customer taps a card or presses Pay on a checkout page, the approval that comes back in a second or two is only the first of several separate exchanges between at least four organisations. Money does not move during that approval. It moves a day or more later, through batch files the customer never sees, and it can move back weeks after that through a chargeback. Model it as one synchronous call with a success flag and you get double charges, orphaned holds and a ledger that never matches the bank.
This article explains the card-network flow from first principles: who the parties are, what authorisation actually does, how capture, clearing and settlement differ, where tokenisation and 3-D Secure fit for online payments, and how to build the merchant-side service so that timeouts, retries and disputes cannot corrupt it. It deliberately stops at the network boundary on one side and at the merchant's own ledger on the other. For a full marketplace pay-in and pay-out design, read designing a payment system; for how one large provider exposes all of this as an API, read the Stripe platform article.
The parties and what each one holds
The common card schemes use a four-party model. The cardholder holds a card issued by an issuer, the bank that extends the credit and bears the risk of the cardholder not paying. The merchant has a contract with an acquirer, the bank that is a member of the card network and takes on the risk of the merchant, for example a merchant that goes bankrupt with undelivered orders outstanding. The card network switches messages between acquirers and issuers, sets the rules, and runs settlement between members.
In practice two more roles sit in the path. Most merchants never talk to an acquirer directly; they integrate with a payment gateway or payment service provider (PSP), which handles card data, routes to one or more acquirers, and often acts as a payment facilitator that aggregates many small merchants under its own acquiring contract. Issuers often outsource their authorisation host to an issuer processor. Each hop is a separate company with its own timeouts, outages and reports.
Authorisation: the real-time path
Authorisation answers one question: will the issuer stand behind this amount on this card right now? The request carries the card number or a token, amount and currency, the merchant category code, how the card was presented, and for online payments the CVV and any 3-D Secure result. The PSP forwards it to the acquirer, the acquirer to the network, and the network routes it by the card's BIN, the leading digits that identify the issuer, to the issuer's host.
Between acquirers, networks and issuers these messages are typically ISO 8583. An authorisation request is message type 0100 and its response 0110; reversals use the 0400 family, with 0420 as the advice form. Fields that surface in PSP reports include the retrieval reference number (data element 37), the authorisation code (38) and the response code (39). Response code 00 means approved; others such as 05 (do not honour) and 51 (insufficient funds) are widely used, but codes and their exact meaning vary by network and PSP, so map them through your PSP's documented categories rather than hard-coding a global table.
An approval does two things at the issuer: it returns an authorisation code, and it places a hold that reduces the cardholder's available credit by the amount. No money has moved. The hold expires after a period set by network rules and merchant category; capturing against an expired authorisation risks a decline or a dispute. If the issuer's host is unreachable, the network may perform stand-in processing, approving or declining on the issuer's behalf within limits the issuer has set; this is why a payment can be approved while a bank is down.
The merchant's own fraud screen runs before the authorisation request, under a strict latency budget; see the real-time fraud detection article.
Capture, clearing and settlement
Capture is the merchant saying the sale is final for a given amount. With separate authorisation and capture, a retailer authorises at checkout and captures at shipment; with a sale (authorise and capture together) the capture is implied. Capture is usually a PSP-level operation: the PSP records it and includes the transaction in the next clearing batch. Capturing less than the authorised amount is generally allowed; capturing more is restricted by network rules, which is why hotels use incremental authorisations.
Clearing happens in batches. The acquirer sends presentments, the financial records of captured transactions, through the network to each issuer, often hours after capture. The issuer matches each presentment to its earlier authorisation, posts the transaction to the cardholder's statement and drops the hold. A presentment that arrives without a matching authorisation, or for a different amount, is exactly what becomes a dispute later.
Settlement is where money moves. The network computes each member's net position for the cycle and funds move between issuers' and acquirers' settlement accounts. Along the way the issuer keeps interchange, a fee set by the network that the acquirer effectively pays the issuer out of each transaction, and the network charges scheme fees to both sides. The acquirer or PSP then funds the merchant, net of its own markup; the total the merchant gives up is the merchant discount. Interchange depends on card type, region, merchant category and how the card was presented, so do not model fees as one percentage. A refund is a new credit transaction that flows through clearing and settlement in the opposite direction; it is not the same as a reversal, which cancels an authorisation before it is captured and usually releases the hold quickly.
Online payments: tokens and 3-D Secure
Card-not-present payments add three mechanisms. First, tokenisation at the PSP: the card number is entered into a field or page served by the PSP, which returns an opaque token. The merchant's servers store and send only tokens, which shrinks the scope of its PCI DSS assessment dramatically, because the card number never touches its systems. The CVV may be used for the authorisation but must not be stored afterwards by the merchant or the PSP.
Second, network tokens: the network issues a token that stands in for the card number on that merchant's transactions, and the issuer updates it when the physical card is reissued. Stored-card payments keep working after a card is replaced, and a stolen network token is less useful elsewhere.
Third, 3-D Secure, the EMVCo protocol behind bank challenge screens. The merchant's PSP sends device and transaction data to the issuer's access control server, which either authenticates the cardholder silently (frictionless) or presents a challenge such as an app confirmation. A successful authentication result travels with the authorisation and, under network rules, usually shifts liability for fraud chargebacks from merchant to issuer. In the European Economic Area, strong customer authentication rules make authentication mandatory for most customer-initiated online card payments, with defined exemptions. Treat authentication as a state with its own timeouts and abandonment.
The merchant payment service
On the merchant side, the payment service owns a state machine per payment and talks to the PSP. Three rules keep it correct. Every request to the PSP carries an idempotency key derived from the payment attempt, so a retry after a timeout cannot create a second authorisation; the design of the key store is covered in the idempotency architecture article. State changes and the events that announce them are written in one transaction with a transactional outbox, so fulfilment never ships an order whose payment row says otherwise. And an unknown outcome is a state: a timeout is neither approved nor declined.
class Payment:
# states: created -> authorizing -> authorized | declined | unknown
# authorized -> captured | voided ; captured -> refunded | disputed
...
def authorize(payment, psp, timeout_s=8):
key = f"auth:{payment.id}:{payment.attempt}"
db.transition(payment, "created", "authorizing")
try:
r = psp.authorize(token=payment.token, amount=payment.amount_minor,
currency=payment.currency, idempotency_key=key,
timeout=timeout_s)
except (Timeout, ConnectionError):
db.transition(payment, "authorizing", "unknown") # never guess
outbox.emit("payment.resolve", payment.id, delay_s=30)
return
with db.tx():
if r.approved:
db.transition(payment, "authorizing", "authorized",
auth_code=r.auth_code, psp_ref=r.reference)
outbox.emit("payment.authorized", payment.id)
else:
db.transition(payment, "authorizing", "declined",
category=r.decline_category) # soft vs hard
def resolve(payment, psp):
r = psp.lookup(idempotency_key=f"auth:{payment.id}:{payment.attempt}")
if r is None or r.status == "failed":
db.transition(payment, "unknown", "declined", category="no_response")
elif r.status == "authorized" and payment.order_cancelled:
psp.void(r.reference) # release the hold
db.transition(payment, "unknown", "voided")
elif r.status == "authorized":
db.transition(payment, "unknown", "authorized", psp_ref=r.reference)
else: # still pending: ask again later
outbox.emit("payment.resolve", payment.id, delay_s=60)Inside the network, a missing response is handled with a reversal so the issuer drops any hold it placed. Your own call to the PSP can still time out after it succeeded, which is why the resolver looks up by idempotency key and never sends a new authorisation with a fresh key.
Worked example: one order from checkout to chargeback
Follow one order through the flow. A customer orders two items totalling 120.00 EUR. The fraud screen passes, 3-D Secure completes frictionlessly, and the PSP returns an approval with authorisation code 4F7Q21; the issuer holds 120.00 against the card. The merchant ledger records nothing yet except the authorisation reference, because no money is owed in either direction.
Next morning one item turns out to be out of stock. The warehouse ships the other and the service captures 90.00. It then releases the remaining 30.00, either through a partial reversal or because the PSP does it automatically on a partial capture; check which, because a forgotten 30.00 hold is a top cause of customer complaints. That night the acquirer's batch clears 90.00 to the issuer, which posts it and drops the hold. Two days later the PSP pays out: 90.00 minus its fee, say 1.85, arrives in the merchant's bank account inside one deposit that also contains hundreds of other payments.
The ledger now needs entries that match three independent sources: its own capture record, the PSP's settlement report line for this payment, and the bank deposit for the whole payout.
day 0 auth 120.00 (memo only, no ledger entry)
day 1 capture 90.00 Dr receivable:psp 90.00 Cr revenue 90.00
day 1 release 30.00 (memo only)
day 3 payout Dr cash:bank 88.15
Dr expense:psp_fees 1.85 Cr receivable:psp 90.00
day 20 refund 25.00 Dr revenue 25.00 Cr receivable:psp 25.00
day 45 dispute 65.00 Dr receivable:disputes 65.00 Cr receivable:psp 65.00On day 20 a 25.00 refund for a returned part clears in the opposite direction. On day 45 the cardholder disputes the remaining 65.00 as not received: the issuer raises a chargeback, the network debits the acquirer, and the PSP debits the merchant, usually with a fee. The merchant can submit the carrier's delivery confirmation as a representment through the PSP; the issuer decides. Until then the 65.00 sits in a disputes receivable.
Failure modes
| Failure | What happens | Defence |
|---|---|---|
| Timeout calling the PSP | Authorisation may exist without your record of it | Unknown state, resolver by idempotency key, void if no longer wanted |
| Double click or client retry | Two authorisations, two holds | Idempotency key per attempt; disable the button; dedupe server side |
| Capture after the hold expired | Capture declined or later disputed | Capture promptly; re-authorise long-lived orders; track auth age |
| Issuer or network outage | Declines spike, or stand-in approvals within limits | Alert on approval rate per issuer; route to a second acquirer if contracted |
| Retrying hard declines | Network penalties, more fraud flags | Retry only soft declines, with backoff and a cap; never retry stolen-card codes |
| Webhook lost or reordered | Order stuck in a stale state | Treat webhooks as hints; poll or fetch the object; process idempotently |
| Settlement mismatch | Ledger and bank disagree | Daily three-way reconciliation; exceptions queue with owners |
Operating it: metrics, reconciliation and trade-offs
Measure the flow at each hop. Approval rate is the headline metric, but it is only actionable when sliced by issuer BIN, country, card type, entry mode and decline category; a drop at a single issuer is an outage, a drop across the board is usually your own change. Track authorisation latency at the 99th percentile against your client timeout, the rate of unknown outcomes and how long they take to resolve, the reversal rate, auth-to-capture age, refund rate and chargeback ratio. Networks monitor merchants with high dispute ratios, so treat that ratio as a compliance metric.
Reconciliation is a daily job, not a quarterly clean-up. Match captures and refunds to the PSP's settlement report, then each payout to a bank deposit, and route exceptions to an owner. Trade-offs to decide up front: separate authorisation and capture adds flexibility but creates expiring holds; a second acquirer adds availability at the price of token portability and reconciliation work; forcing 3-D Secure cuts fraud but costs conversion where it is not mandatory.
What to do next
- Draw your own version of the four-party diagram with the actual companies in each box, and note each one's timeout and status page.
- Model payment states explicitly, including an unknown state, and add a resolver that looks up outcomes by idempotency key.
- Confirm that your servers never see card numbers or store CVV, and find out which PCI DSS self-assessment questionnaire applies to you.
- Measure auth-to-capture age and make sure partial captures release the remaining hold.
- Build daily three-way reconciliation: ledger, PSP settlement report, bank deposit.
- Dashboard approval rate by issuer, country and decline category, and alert on the chargeback ratio.
- Write down which decline categories you retry, how often, and with what backoff, and review it against your PSP's guidance.