DEV Community

Payneteasy
Payneteasy

Posted on

The authorization hold expires before you capture, and the window is different for every network

Debugging a delayed-capture flow for a marketplace that holds funds until a courier confirms delivery, sometimes 5-6 days out. Captures started failing with generic decline codes for a subset of orders, no pattern by amount or issuer.

Turned out the auth hold had simply expired. Visa gives you roughly 7 days on a standard hold, Mastercard closer to 30, but issuers can and do shorten that window on their end regardless of what the network default says. Once the hold drops, the processor doesn't send you a webhook telling you it's gone. You just find out when the capture call bounces.

The fix ended up being boring: track hold creation timestamp per network, re-authorize automatically at day 5 for Visa transactions instead of waiting for the courier, and treat capture failures past that window as "needs re-auth" rather than "payment failed" in the retry logic. Customer sees nothing, ledger stays clean.

What surprised me is how little of this is documented anywhere central. Every gateway I checked either buries the expiry window in a PDF or doesn't mention it at all, and you only find the real number by hitting the wall in production.

Anyone tracking hold expiry per-network as a first-class field in their payment state machine, or is everyone just reacting to the decline like I was?

Top comments (0)