Guide · August 2026
The second payment on a Shopify deposit declined — what happens next, and what recovers it
The deposit went through weeks ago; today the balance charge against the saved card came back declined. This page is the mechanics of that moment: what a merchant-initiated charge actually is, why issuers refuse them, what Shopify does when one fails — which is less than you might hope — and the retry, notify and card-update practice that recovers the order. No decline-rate statistics, because nobody publishes honest ones for deposit balances.
The short version
- The balance is charged to a card Shopify vaulted at checkout, with the customer absent. Payment networks call this a merchant-initiated transaction; Shopify models the permission behind it as a payment mandate.
- Shopify records the failure and stops. Nothing in the documented charge flow retries the payment or emails the customer — recovery belongs to whatever fired the charge: an app, or you.
- The decline code decides the fix. Insufficient funds is genuinely retryable; an expired card is not; a fraud-flagged decline means stop retrying entirely.
- Retries are capped and spacing matters. Card networks limit reattempts — Stripe’s guidance is a maximum of eight — and issuers read hammering as fraud.
- Recovery has three legs: a bounded retry ladder, an email the customer actually receives, and a way to put a working card back on the order. Run all three or the order sits half-collected.
What the second charge actually is
Start with what fired the charge, because everything about recovery follows from it — and it is not a checkout. When your customer paid the deposit, Shopify saved their card and, with it, their permission to be charged again. Shopify’s Admin API models the pair as a single object, a PaymentMandate — in its words, “a payment instrument and the permission the owner of the instrument gives to the merchant to debit it.” The card alone is not the asset. The permission is.
The payments industry calls the later charge an off-session, or merchant-initiated, transaction. Stripe’s documentation states the arrangement plainly: “Creating an agreement (sometimes called a mandate) up front allows you to charge the customer when they’re not actively using your website or app.” When the card is saved with that consent, the processor “marks any subsequent off-session payment as a merchant-initiated transaction (MIT) so that your customers don’t have to come back online and authenticate.” Stripe’s minimum terms for the agreement are worth reading, because they are what a deposit checkout is silently doing: the customer’s permission for you to initiate the payment, the anticipated frequency, and how the amount will be determined. A checkout that shows the split and the due date before the customer pays is that agreement, doing its job.
On the Shopify side, the order carries its usable stored methods — the API exposes “the list of vaulted payment methods for the order with their permissions” — and the balance is charged against one of them with a dedicated mutation, orderCreateMandatePayment. One line of its documentation matters more than all the rest here: “The mutation processes the payment asynchronously and returns a Job for tracking the payment status.”
A balance charge is a question sent to the issuer, not an instruction. The answer comes back on its own schedule, as a status — Shopify’s transaction-status enum includes PENDING, FAILURE, ERROR and SUCCESS — and when the answer is no, the reason arrives as an error code on the transaction. Which code, it turns out, is most of what you need to know.
Why the issuer said no
The deposit succeeded because the customer was there, paying with a card they had just chosen. The balance is decided under different conditions. Stripe describes the issuer’s side of every charge: “When your customer’s card issuer receives a charge, their automated systems and models decide whether to authorize it. These tools analyze signals such as spending habits, account balance, and card data including expiration date, address information, and CVC.” Every one of those signals can move in the weeks between your two charges. The card was present at checkout. Nobody is present now.
Start with the mundane causes. Insufficient funds — in Stripe’s words, “if a customer has insufficient customer funds or credit, the card issuer declines the transaction” — and a card that expired somewhere between checkout and the due date, which a longer gap gives more room to happen in. Then there is the less mundane one: issuers decline on suspicion of fraud, which Stripe notes “can be triggered by large purchases”. A deposit balance on made-to-order work is often precisely that — a large, unusual, customer-absent charge. That reading is mine, not Stripe’s sentence, but the ingredients are theirs: the charge pattern that makes deposits useful overlaps with the pattern issuers are primed to distrust.
One regulatory case sits apart. For merchants under Strong Customer Authentication rules, Stripe notes that off-session payment attempts “might also require authentication and fail with an authentication_required decline code” — and completing such a payment means bringing the customer back online to authenticate. That is a challenge, not a refusal. No retry ladder resolves it without the customer.
What you actually see when any of this happens is a code. The issuing bank returns a network decline code — 2-4 digits, and the meaning differs by card network; Mastercard calls its advice codes Merchant Advice Codes — and Shopify translates the failure into its own error enum on the order transaction. The values you will meet on a deposit balance:
| Code | Shopify’s meaning | What actually fixes it |
|---|---|---|
| EXPIRED_CARD | “The card is expired.” | Retrying cannot work — the vaulted card is not a card anyone can charge. A network account updater may have already pushed the replacement card silently; if not, the customer has to supply one. |
| INSUFFICIENT_FUNDS | “There are insufficient funds available to complete the transaction.” | The cleanest retryable failure. The money was not there on the day; a retry a few days later, with an email to the customer in between, is the whole playbook. |
| DO_NOT_HONOR | “The issuer declined the transaction without providing a specific reason.” | The catch-all. One or two spaced retries are reasonable; if it persists, the conversation the customer needs to have is with their bank, not with you. |
| CALL_ISSUER | “The issuer declined the transaction, the customer should contact their issuer for more details.” | The bank has told you what it wants: the customer, on the phone, to them. Retrying before that call happens is noise. |
| FRAUD_SUSPECTED | “The transaction was declined due to suspected fraudulent activity.” | Stop the ladder. Issuers can read repeated attempts after a fraud decline as more evidence of fraud, and that can raise declines on future legitimate charges. |
| CARD_TESTING | “The transaction was declined due to suspected card testing activity.” | Stop retrying and look at the order itself. This code means the issuer suspects the card, not the purchase — treat it as a review case, not a recovery case. |
The companion table for subscription-style billing-attempt failures — including the silent case where an authentication challenge produces no notification at all — is in the 50% deposit guide. Different mutation, same banks, same answers.
What Shopify does when it fails
Shopify records the failure. That is the whole list. The transaction lands with its failure status and its error code, and the order keeps showing the balance as outstanding. Nothing in the documentation of the mandate-payment flow describes a retry, a schedule, or a message to the customer — the mutation charges the card once, asynchronously, and reports how it went.
This is consistent with how Shopify documents partial payment everywhere else. Its built-in partial-payments feature — draft orders with payment terms, Shopify Plus only — is documented as a recording system: “After you record a partial payment for an order, the order status changes to Partially paid.” The page describes recording payments a customer has made. It does not describe charging anyone, retrying anything, or emailing anybody.
If you were planning to wire your own dunning together in Shopify Flow, look at the trigger’s scope before you build. Flow’s failure automation is subscription-shaped: “The subscription billing attempt failure trigger starts a workflow when a subscription billing attempt fails.” A deposit balance charged against an order mandate is not a subscription billing attempt, so as documented, the trigger you need is scoped to the wrong object. Flow’s “customer payment method updated” trigger is broader — useful for noticing that a customer fixed their card — but noticing is not recovering.
Whose job is it, then? Shopify’s developer documentation places scheduling the balance charge and handling its failures on the app that created the deposit plan — the 50% deposit guide quotes its wording in full. The practical consequence: when the second payment declines, what happens next is exactly what your app — or you — decided in advance would happen next. If nothing was decided, nothing happens.
The recovery practice
Recovery has three legs, and each covers failures the other two cannot. A retry recovers the empty-account-on-the-day cases. An email recovers the cases where the customer can fix something. A card update recovers the cases where the vaulted card itself is dead. An app or a process that runs only one of the three is leaving the other two categories of order half-collected.
A retry ladder — spaced, and capped
The cap is not etiquette; it is the networks’ rule. Stripe’s decline documentation: “Be aware that card networks limit the number of times you can reattempt a single charge. We recommend a maximum of eight retries for charges that permit retries. Card issuers might see creating additional retries as potential fraud, which can result in increased declines for legitimate charges.” Excessive retrying does not just fail — it makes the card’s future worse.
Spacing is what the automated tooling optimises. Stripe’s Smart Retries times attempts using data-driven signals rather than a fixed schedule, with a recommended default of 8 tries within 2 weeks. You do not need the automation; you need the shape it implies — a handful of attempts spread across days, with a hard stop, not a cron job that hits the card every hour. And the ladder must respect the code it is climbing against: for FRAUD_SUSPECTED, the right number of further attempts is zero.
A retry must be a retry, not a second charge
Shopify’s documentation offers a safeguard here: “Each payment request requires a unique idempotencyKey to prevent duplicate charges. Subsequent calls with the same key return the original payment result rather than creating a new payment.” That is what the docs say. It is not what I measured. Replaying a used key against the live API — my dev store, a real order — got the payment fully re-processed against the order’s current state, and a never-before-seen key hit exactly the same wall; what stopped both was Shopify’s own server-side check that the order still has an outstanding balance above zero. The key buys you no deduplication here. Run that same check on your side, first: read the order’s outstanding balance immediately before every attempt and abort if it is zero. That is the guard that holds, and it is the one DepositDesk’s own capture path runs before each fire. Keep the key stable when you resend a call that timed out — not for dedup, but so the second call is still traceable to the first.
An email the customer actually receives
The customer is not on your site when the charge fails — that is the definition of off-session — so the notice has to travel to them. Stripe’s guidance for exactly this case: “If your customer isn’t available to make a payment or update a payment method, notify them (for example, send them an email or in-app notification) to visit your website or application.” Its revenue-recovery tooling sends email on three events — a failed payment, an expiring card, a payment method needing an update — and those three are a good checklist for any deposit process. The email’s job is precise: get the card fixed before your last attempt, not after it.
A way to put a working card back
An expired or reissued card is the failure a retry can never touch, and it has two fixes. The first can happen without anyone noticing: the card networks run account-updater services that push a reissued card’s new number and expiry to merchants holding it on file. Visa’s version, VAU, is “a secure electronic exchange of account information updates between participating Visa card issuers and acquirers for credential-on-file merchants”. Mastercard’s equivalent is Automatic Billing Updater — Mastercard’s own public pages on it are thin, so the clearest description I found comes from one participating bank’s customer FAQ, which describes it as providing account changes such as card number and expiration-date updates to merchants set up for recurring payments. Participation varies by issuer and gateway; treat the silent fix as a bonus, not a plan.
The second fix is the customer. Shopify documents both directions for subscription contracts: the merchant can replace the card in the admin — “click More actions next to the payment method that you want to update, and then click Replace card” — or send the customer a self-service link: “click Send link to update card, and then click Send email”. Note the scope honestly: those flows are documented for subscription contracts. For a deposit order, the card-update path is the app’s to provide — ask what it is before you install, because the day you need it is not the day to discover there isn’t one.
Doing this by hand
Nothing above is conceptually hard. It is a checklist, and every item on it is small:
- Notice the failure. The charge is asynchronous — the decline arrives as a status on a job, not as an alarm. Noticing is itself a task, and it is the one that silently doesn’t happen.
- Classify the code. Retryable, needs-the-customer, or stop-entirely — the table above. Retrying an expired card wastes an attempt; retrying a fraud flag does damage.
- Re-read the balance, then retry. Check the order’s outstanding balance immediately before every attempt and stop if it is zero — that read, not the idempotency key, is what keeps a retry from becoming a second charge. Then space the attempts days apart, a bounded number of times, under the network cap.
- Email the customer after each failure. So the fixable problems get fixed while attempts remain.
- Chase the card update, then escalate. When the ladder runs out, a person takes over.
The problem is not any step; it is who runs the loop, on time, every time, per failed order. By hand, you are the scheduler, the classifier, the email system and the escalation path — for a $1,500 balance on a $3,000 commission, that is real money administered from memory. I will not invent a recovery-rate statistic to scare you with. The structural point stands without numbers: a recovery process that depends on you remembering is a recovery process that degrades exactly when you get busy — and the failure mode is invisible, an order quietly half-collected until someone thinks to look.
This is the part where I tell you what I build. DepositDesk is a $29-a-month flat-rate deposits app for standard Shopify plans, with a 14-day free trial, no per-transaction fee, no revenue share and no cap on order value — and this page is a description of its decline handling: DepositDesk retries a declined balance after 1, 3 and 7 days, emails the customer each time a charge fails, and flags the order for you when the ladder runs out. Three spaced attempts across eleven days — comfortably inside the networks’ ceiling. Every order’s deposit and balance status sits in one dashboard, re-checked against Shopify daily to catch anything that drifts, and if you cancel the order in Shopify, DepositDesk sees the cancellation and stops the scheduled balance charge automatically.
Its real limits, because you should know them before you install anything: Online Store channel only — not POS, not B2B, not draft orders. It needs an Online Store 2.0 theme, because the deposit option is a theme app block you add in the theme editor. It needs one of the four vaulting-capable gateways — Shopify Payments, PayPal Express, Stripe, or Adyen. And it is one deposit plus one later balance, not an instalment plan. On the third leg above, be exact about what you are getting: the decline emails tell the customer a retry is coming, not to go and replace their card, and DepositDesk sends Shopify’s card-update email when a saved method is revoked, not when a charge declines. On a dead card, that leg is you, working from the flagged order. Every feature is free for 14 days — the install lives on the homepage.
Related: pre-order deposits is where the deposit-to-balance gap runs longest and expired cards bite hardest; writing a non-refundable deposit policy covers what you keep when recovery ultimately fails; deposit accounting shows how a half-collected order lands in your books; and taking a deposit on a custom order is the full map of methods if you are still choosing one.
Questions merchants actually ask
Does Shopify retry a declined deposit balance charge?
No. Shopify's documentation of the mandate-payment mutation describes one asynchronous charge and a Job for tracking its status — no retry schedule, no customer email, no escalation. Recovery belongs to whatever fired the charge: the app that scheduled it, or you. If nothing owns it, nothing happens, and the order sits with its balance outstanding.
Why did the second payment decline when the deposit went through fine?
Because the issuer decides each charge on its own merits, and the signals changed. Stripe describes issuers analysing spending habits, account balance and card data including the expiration date on every charge. Weeks or months sit between your two charges, and in that gap the card can expire, the account can be empty on the day, or an off-session charge for a large amount can look like fraud.
Can I just retry the declined charge right away?
Usually you shouldn't. Card networks limit how many times a single charge can be reattempted — Stripe recommends a maximum of eight retries and warns that issuers can treat excessive retries as potential fraud. Spaced attempts over days work; hammering does not. And for a fraud-flagged decline code, the right number of further retries is zero.
Could a retry double-charge the customer?
Only if nothing checks the balance first. Shopify's documentation says the mandate-payment mutation requires a unique idempotency key and that subsequent calls with the same key return the original payment result rather than creating a new payment. Measured against the live API, that is not what the mutation does: a replayed key is fully re-processed against the order's current state, and a brand-new key hits the same wall. What actually stops the second charge is reading the order's outstanding balance immediately before every attempt and aborting if it is zero — Shopify enforces the same check on its side. Reuse the key when you resend after a timeout, though: a fresh one abandons the trace of the original fire.
What if the card expired before the balance came due?
A retry cannot fix an expired card. Two things can: the card networks' account-updater services — Visa's Account Updater and Mastercard's Automatic Billing Updater — which push reissued card details to participating merchants who store cards on file, and the customer, who can supply the new card. Shopify documents card-replacement flows for subscription contracts; for a deposit order, ask your app what its card-update path is.
What if the bank wants the customer to authenticate the charge?
Then no retry ladder fixes it without them. Stripe's documentation says off-session attempts for merchants under Strong Customer Authentication rules can fail with an authentication_required decline code, and completing such a payment means bringing the customer back online to authenticate. This is a challenge, not a refusal — the fix is the customer, present, not another automated attempt.
What happens if every retry fails?
The order keeps its balance outstanding, and a person has to take over — every ladder that runs out ends with a phone call. What you keep if the sale ultimately falls through is not a Shopify setting; it is your deposit policy, and it is much easier to point at a written one than to invent one mid-dispute.
Sources for this page: Shopify’s Admin API references for PaymentMandate, orderCreateMandatePayment, OrderPaymentCollectionDetails, its order-transaction status and error-code enums and its subscription billing objects; Shopify’s help-centre pages on partial payments, Shopify Flow triggers and managing subscription contracts; Stripe’s documentation on card declines, setup intents, automatic collection and revenue recovery; Visa’s Account Updater developer documentation; and, for Mastercard’s Automatic Billing Updater, one participating bank’s customer FAQ (First National Bank Alaska) — all read August 2026. The measured behaviour of orderCreateMandatePayment under a replayed idempotency key is my own test against a live dev store, not documentation, and the page says so where it is used. Where a statement is my judgement rather than documentation, the page says so in place. If you find something here that is wrong, I would rather hear it: support@depositdesk.app.