What you’ll build

A dunning step: a renewal failed last night with insufficient_funds. Retry it now, optionally against a new card the customer just added.

The call

Use retry_failed_charge (a composite tool).

{
  "name": "retry_failed_charge",
  "arguments": {
    "transaction_id": "6ba7b813-9dad-11d1-80b4-00c04fd430c8",
    "payment_method_id": "6ba7b815-9dad-11d1-80b4-00c04fd430c8",
    "idempotency_key": "dunning-2026-04-21-6ba7b813"
  }
}
ArgumentMeaning
transaction_idThe failed transaction to retry.
payment_method_idOptional. If omitted, EPD retries against the same card. If present, retries against the new card.
idempotency_keyPass a stable key per dunning attempt so accidental re-runs do not double-charge.

When to retry against the same card

  • Decline reason was insufficient_funds and a few days have passed (paydays).
  • Decline reason was gateway_error (transient).

When to retry against a different card

  • Decline reason was expired_card and the customer added a new one.
  • Decline reason was card_declined repeatedly — the issuer is consistently saying no.

What you get back

{
  "transaction_id": "9c1d2e3f-4a5b-4c6d-8e7f-0123456789ab",
  "status": "succeeded",
  "amount": 2999,
  "currency": "usd"
}

Or:

{
  "error": {
    "type": "processing_error",
    "code": "card_declined",
    "message": "Card was declined.",
    "request_id": "req_a1b2c3d4e5f67890abcdef0123456789"
  }
}

Stop retrying

Most issuers will eventually mark a card as “do not retry” if you keep trying. Plan a finite dunning curve — e.g. retry on day 1, day 3, day 7, then give up — and notify the customer at each stop.

EPD’s built-in subscription dunning already runs smart retries when a renewal order fails (order.failed on the underlying renewal order). Use retry_failed_charge only for one-off orders or when you want explicit control.