Email API

Failed Payment and Dunning Email Sequence: Timing, Copy, and API Sends

Design a dunning email sequence for failed subscription payments: how many emails, when to send, what to say, when to pause access, and the API request.

Roughly a fifth to a third of subscription churn is involuntary: a card expired, a bank declined a transaction, a limit was hit. A dunning sequence, meaning a short series of emails that gets the customer to update their card, recovers a large share of it. This guide gives you a four-email schedule, the copy for each, the state machine to drive it, and the send request.

Quick answer

Send four emails over about two weeks, aligned with your processor's retry schedule: day 0 (payment failed, we will retry), day 3 (retry failed, please update your card), day 7 (final reminder, access pauses on day 14), day 14 (subscription paused, one click to restore). Keep every email short, link straight to the billing page, and stop the sequence the instant a payment succeeds.

Align with the processor

Stripe, Paddle, Braintree and most billing systems retry a failed charge automatically several times over one to three weeks, and they emit events for each attempt (in Stripe: invoice.payment_failed, invoice.payment_action_required, invoice.paid). Drive your emails from those events rather than from a timer of your own, so you never email "please update your card" ten minutes after a successful retry. If the failure reason is a hard decline such as a stolen or closed card, skip the "we will retry" message and go straight to "update your card".

The four emails

  1. Day 0, "Your payment did not go through": the amount, the last four digits, the decline reason in plain words if the processor gave one (expired card, insufficient funds), a note that you will retry automatically, and a link to update the card now. Reassure: nothing changes today.
  2. Day 3, "Action needed: update your payment method": the retry also failed, the service continues for now, a button to the billing page. This is the email that recovers most accounts.
  3. Day 7, "Final reminder before your account is paused": a clear date on which access pauses, what happens to their data (nothing is deleted), and the button again.
  4. Day 14, "Your subscription is paused": access is paused, data retained for N days, one button that restores everything after a successful payment. Also a reply address for people whose card is fine and something else went wrong.

The send request

Every message in the sequence is the same call with different copy; parameterise on the step number and the failure reason:

const res = await fetch("https://api.oqumail.com/api/v1/emails", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + process.env.OQUMAIL_API_KEY,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    from: "billing@yourdomain.com",
    to: customer.email,
    subject: "Action needed: update your payment method for Acme",
    html: '<p>Hi ' + escapeHtml(customer.firstName) + ', we could not charge your Visa ending ' + card.last4 + ' for USD ' + amount + ' (reason: ' + reason + ').</p><p><a href="' + billingUrl + '">Update payment method</a></p><p>Your account stays active while we sort this out. Reply to this email if you need help.</p>',
    text: "We could not charge your Visa ending " + card.last4 + " for USD " + amount + ". Update it here: " + billingUrl
  })
});
if (!res.ok) throw new Error("send failed: " + res.status);

The state machine

  • Store dunning_step (0 to 4) and dunning_started_at on the subscription.
  • On payment_failed: if dunning_step is 0, send email 1 and set step 1. Otherwise do nothing; the schedule handles the rest.
  • A daily job advances steps by elapsed days since dunning_started_at, sending the next email only if the step has not been sent.
  • On invoice.paid: reset dunning_step to 0, clear dunning_started_at, and if the account was paused send a short "you are back" email.
  • On step 4: pause access and set a data-retention deadline. Do not delete anything during dunning.
  • Make every step idempotent by recording sent_at per step. Webhooks and cron jobs both repeat.

Copy and tone

People do not read dunning emails carefully, so lead with the action and the amount. Never blame the customer ("you failed to pay"); banks decline good cards all the time. Never threaten in email 1. Avoid words that spam filters and nervous customers both dislike, such as "urgent", "suspended", and exclamation marks. Use the customer's name and the last four digits of the card so the email is obviously genuine, because payment emails are the most impersonated category of phishing and your customers know it.

Sending it from a trustworthy address

Send from billing@ on the same domain your customers log in to, with DKIM aligned, so the message survives the phishing filters that scrutinise anything mentioning a card. Keep billing@ a real mailbox: people reply to dunning emails with "I updated it, please retry" and "my company changed, send the invoice to X", and those replies are recovered revenue. OquMail gives you the send API and a billing@ inbox on the same free plan, plus a delivery log for each message that shows whether the customer's mail server accepted it, which matters when someone insists they were never warned before the pause.

Common questions

Should I pause access or cancel?

Pause. Cancelling deletes the relationship; pausing keeps the data and the settings so a single successful payment restores everything. Cancel only after the retention period.

Is a pre-dunning email worth sending?

Yes, for card expiry. Processors tell you the expiry month in advance; an email 10 days before saying "your card ending 4242 expires this month" avoids the failure entirely.

How many emails is too many?

Four over two weeks is the upper bound. Sending daily creates unsubscribes and complaints, and complaints hurt every other email you send from that domain.

Free business email on your own domain

OquMail gives you up to 15 mailboxes on your domain — free — with guided SPF/DKIM/DMARC, webmail, IMAP/SMTP for any mail app, and a send API. Most teams are live in under fifteen minutes. Start at oqumail.com.

Get started free

Ready for business email on your domain?

Up to 15 free mailboxes, guided DNS, webmail, and a transactional API — start in minutes.

Create your free workspace