---
name: stripe-failed-payments
description: "Every weekday: Stripe invoices whose payment failed, with amount, decline reason and next retry, and a question about which customers to email. Use when the user asks for this, or when it runs on a schedule."
---

# Stripe failed payments to chase

Every weekday: Stripe invoices whose payment failed, with amount, decline reason and next retry, and a question about which customers to email.

Involuntary churn is the cheapest churn to fix: the customer still wants the product, their card just expired. Smart Retries recover part of it on their own, and the rest turns quietly into canceled subscriptions a few weeks later.

This skill looks only at what the retries haven't fixed, sorts it by money and urgency, and asks which customers deserve a personal note with a payment link. Nothing goes out until you pick.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- A restricted Stripe key with read access to Invoices, Charges, Customers and Subscriptions in `STRIPE_API_KEY`, or the Stripe MCP server.
- For the drafts: access to the mailbox you send from, such as a Gmail connector. Without it the agent writes the emails into the card.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **List open invoices with failed attempts** (Stripe): Page through `GET /v1/invoices?status=open` and keep invoices with an `attempt_count` of 1 or more and `amount_remaining` above zero. Add invoices with `collection_method=send_invoice` whose `due_date` has passed.
2. **Read why each one failed** (Stripe): Note `next_payment_attempt` (null means Stripe has stopped retrying), the subscription's status (`past_due` or `unpaid`), and the customer's latest failed charge: `failure_code` and `outcome.reason`, for example `expired_card` or `insufficient_funds`.
3. **Rank them**: Invoices with no retries left go first, then by `amount_remaining`. An expired or lost card will not succeed on a retry, so it needs the customer; insufficient funds often clears on the next attempt.
4. **Ask before emailing**: Post the list and ask which customers to contact. For the ones picked, draft a two-line email each with the invoice's `hosted_invoice_url`, where they can update the card and pay, and leave the sending to the person.

## Route B: the browser

### What you need

- Signed in to the Stripe Dashboard with a role that can view invoices, customers and payments (Support Specialist, Analyst or higher), live mode on.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://dashboard.stripe.com/invoices. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **List the open invoices**: Open `https://dashboard.stripe.com/invoices` and pick the **Open** view. Open invoices that have failed carry a `Past due` or `Retrying` badge in the status column; hover the badge for the explanation. Click **Edit columns** to show **Due date** and **Amount due**, and **Export** the list if it runs past one page.
2. **Read why each one failed**: Open each past-due or retrying invoice. The invoice page lists the payment attempts with the decline message for each (an expired card, insufficient funds, a generic decline) and states when Stripe will retry next or that the automatic retries have ended. Note the subscription's status shown on the same page.
3. **Add invoices sent by email that are late**: In the Open view sort by **Due date** and keep invoices whose due date has passed and that were sent for manual payment rather than charged automatically; they have no retry schedule and need a person either way.
4. **Rank and ask**: Put the invoices with no retries left first, then the rest by amount due. Expired and lost cards will not clear on a retry; insufficient funds often does. Post the list and ask which customers to email. For the ones picked, copy the invoice payment page link from the invoice and draft a two-line email each. Do not click **Charge customer**, **Retry** or **Send invoice**.

Note: The invoice list shows a page at a time; use Export when there are more than a few dozen open invoices. Retry timing is shown on the invoice page in the account's time zone.

## The report

- Total **still owed** on failed invoices, and how many have no retries left.
- One row per invoice: customer, amount, decline reason, next retry date.
- The question: which customers to email, with quick answers for all, only those out of retries, or none today.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "stripe-failed-payments/<date of this run, e.g. 2026-10-16>",
  "item_key": "stripe-failed-payments",
  "project": "Acme",
  "source": "Stripe failed payments to chase skill",
  "kind": "action",
  "title": "6 failed payments to chase, $2,914 open",
  "summary": "**6** invoices failed and **$2,914** is still open. **2** have no retries left.",
  "action": {
    "request": "Which customers should I email with a link to update their card and pay?",
    "options": [
      "Email all 6",
      "Only the 2 with no retries left",
      "Only expired cards",
      "Skip today"
    ]
  },
  "widget": {
    "type": "Table",
    "props": {
      "columns": [
        "Customer",
        "Amount",
        "Reason",
        "Next retry"
      ],
      "align": [
        "left",
        "right",
        "left",
        "left"
      ],
      "rows": [
        [
          "Kestrel Design",
          "$1,188",
          "expired_card",
          "None left"
        ],
        [
          "Oakridge Dental",
          "$588",
          "insufficient_funds",
          "Oct 19"
        ],
        [
          "Bluefin Analytics",
          "$396",
          "card_declined",
          "None left"
        ],
        [
          "Harbor & Pine",
          "$348",
          "insufficient_funds",
          "Oct 18"
        ],
        [
          "Lumen Tutoring",
          "$245",
          "expired_card",
          "Oct 20"
        ],
        [
          "Sato Consulting",
          "$149",
          "card_declined",
          "Oct 17"
        ]
      ]
    }
  }
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

## Run it on a schedule

Suggested: Weekdays at 10:00 (`0 10 * * 1-5`). From cron, with the agent signed in on that machine:

```bash
0 10 * * 1-5 claude -p "Run the stripe-failed-payments skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/stripe-failed-payments#schedule

Source: https://briefkin.dev/skills/stripe-failed-payments
