Card authorization reversal can end a hold, free cash and show what may next post to a card or acct as each case may be.
For an issuer program, a reversal is not the same as a refund. A reversal changes an authorization before settlement; a refund is a new transaction after a purchase was captured. The ledger, available balance and customer-facing status need to reflect that difference.
Stripe Issuing exposes four authorization states on current API versions: pending, closed, reversed and expired. The transitions between them are what a card program must reconcile.
Where a reversal sits in the card flow
An approved authorization reserves funds. Stripe says it holds the approved amount in the Issuing balance until the authorization is captured, voided or expires without capture.
The next event determines the accounting treatment:
| Event | Authorization effect | Balance effect |
|---|---|---|
| Full capture | Status becomes closed | Hold becomes a transaction |
| Full reversal | Status becomes reversed; amount becomes zero | Voided amount returns to available balance |
| Partial reversal | Authorization stays pending | Surplus held funds release immediately |
| Expiry without capture | Status becomes expired on current versions | Expired amount returns to available balance |
This lifecycle belongs in the same control map as clearing and settlement. Card program reconciliation covers the downstream matching work.
Full and partial authorization reversals
A full reversal voids the remaining authorization. Stripe sends an issuing_authorization.updated event, sets the authorization to reversed and reports an amount of zero. The reserved funds return to the Issuing balance.
A partial reversal reduces the amount that remains authorized. Stripe says the original authorization’s amount and merchant_amount decrease, while surplus held funds return to the available balance immediately. The authorization can remain pending because a merchant may still capture the reduced amount.
That creates two values worth tracking:
- the amount originally approved;
- the amount still available for capture after reversals and partial captures.
Do not overwrite the first value with the second. Keeping both makes disputes, balance explanations and late captures easier to investigate.
Expiry is related, but it is not a merchant reversal
Stripe can release a hold after an authorization expires without capture. On API versions 2025-03-31.basil and newer, the status is expired; earlier versions can report the same outcome as reversed.
Version-aware handling matters during migrations. If one service expects only reversed while another uses expired, the same economic event can be counted twice or left open.
Stripe also notes that the authorization amount after expiry can represent a remaining amount that may still be captured late. A program should therefore retain the authorization record and continue matching later network activity instead of deleting the hold as soon as the available balance is restored.
Webhooks are the system’s change feed
Stripe emits issuing_authorization.created when an authorization is created and issuing_authorization.updated when it changes. A robust consumer treats those events as updates to one authorization object, not as separate purchases.
Use the authorization ID as the stable identity. For every event:
- verify the webhook signature;
- store the event ID so replay is safe;
- fetch or apply the newest authorization state;
- record amount changes as ledger hold releases or captures;
- wake any reconciliation case waiting on that authorization.
Events can arrive more than once. Event processing needs its own idempotency guard even if the original authorization decision used a reliable real-time webhook.
Partial captures create edge cases
Stripe’s lifecycle table shows that a partial capture leaves an authorization pending. A later full reversal of the remaining balance closes it, while expiry after a partial capture can also produce closed.
The application should not infer status from a single amount comparison. Store the network-facing status, the total approved amount, captured transactions, reversed amount and remaining hold. Then reconcile the equation rather than guessing from one field.
An incremental authorization complicates the history further. Stripe sends another issuing_authorization.request for the original object. If the increment is approved, the top-level amount increases and the extra amount is deducted from the Issuing balance. Stripe says approval of an increment also extends the expiration date.
Customer balance and statement rules
Customers usually experience a reversal as a pending card charge disappearing or shrinking. The program ledger should restore spendable balance when the provider releases the hold, while keeping an audit trail that explains why.
Use distinct labels for:
- authorization hold placed;
- hold reduced by partial reversal;
- hold released by full reversal;
- hold expired;
- purchase captured;
- refund received after capture.
Avoid calling every release a refund. That language suggests settled money moved back, which is not what happens when an uncaptured hold is voided.
Controls to test before launch
- Full reversal before any capture.
- Partial reversal followed by capture of the reduced amount.
- Partial capture followed by reversal of the remainder.
- Expiry with and without an earlier partial capture.
- Late capture after expiry.
- Duplicate and out-of-order webhook delivery.
- An API-version change from
reversedtoexpiredsemantics. - Available-balance restoration that is atomic with the ledger update.
Test helpers can simulate reversals in Stripe Issuing test mode. Stripe’s reverse helper accepts a reverse_amount; omitting it reverses the total amount. Production reversals still originate from merchant and network activity, so tests should also cover asynchronous updates.




