---
name: stripe-daily-revenue
description: "Each morning: yesterday's gross revenue, refunds and net from Stripe, how many customers paid you for the first time, and any dispute that came in. Use when the user asks for this, or when it runs on a schedule."
---

# Stripe daily revenue report

Each morning: yesterday's gross revenue, refunds and net from Stripe, how many customers paid you for the first time, and any dispute that came in.

Checking the Stripe app first thing to see whether yesterday was a good day is a habit most founders have and few enjoy. The home screen shows today's partial numbers, mixes currencies and leaves refunds for another page.

This skill settles it at 7:00 with one closed day, midnight to midnight in your timezone, counted from Stripe's balance ledger so fees, refunds and foreign currencies are already accounted for. The line people end up watching is the count of new paying customers.

## 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 that can read Balance, Charges, Customers and Disputes, in `STRIPE_API_KEY`, or the Stripe MCP server.
- The timezone your day starts in, if it differs from the Stripe account's.

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

### Steps

1. **Fix the day**: Take yesterday from 00:00 to 24:00 in the timezone the business reports in (the Stripe account's timezone unless you say otherwise) and turn both ends into Unix timestamps.
2. **Read the balance ledger** (Stripe): Page through `GET /v1/balance_transactions` with `created[gte]` and `created[lt]` for that day. Sum `amount` for types `charge` and `payment` as gross, `refund` and `payment_refund` as refunds, and add up the `fee` field across all of them; amounts are already in your settlement currency.
3. **Find first-time payers** (Stripe): For each customer with a successful charge that day, run a Charges search such as `customer:'cus_123' AND status:'succeeded' AND created<1760500800` with the day's start. No earlier result means yesterday was their first payment; an earlier one long ago is a reactivation.
4. **Check for disputes** (Stripe): List `GET /v1/disputes` with `created[gte]` for the same day. A new dispute goes at the top of the card with its amount, `reason` and `evidence_details.due_by`.
5. **Write the report**: Gross, refunds, net, fees, the number of successful charges, new paying customers with their plans, the largest single payment, and the change against the day before and the same weekday last week.

## Route B: the browser

### What you need

- Signed in to the Stripe Dashboard with a role that can view payments, customers and reports (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/reports/balance. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Open the Balance summary report for yesterday**: Open `https://dashboard.stripe.com/reports/balance`, set the date range to yesterday only and the time zone to the one your day starts in. In **Balance change from activity** read the `charge` row for gross, fee and net, the `refund` row for refunds, and the count column for the number of payments. Amounts are already in your settlement currency.
2. **Fall back to Payments if the day is not complete**: The report fills in by 12:00 PM the next day. If yesterday is missing, open `https://dashboard.stripe.com/payments`, set the **Date** filter to yesterday, pick the **Succeeded** view and total the **Amount** column (click **Export** when the list runs past one page), then do the same with the **Refunded** view.
3. **Find first-time payers**: On the Payments page for yesterday, open each succeeded payment and click through to the customer. Under the customer's **Payments** section, nothing older than yesterday means a first payment; a much older payment means a reactivation. Note the plan from the invoice or description.
4. **Check for disputes**: Open `https://dashboard.stripe.com/disputes` and filter the date to yesterday. For any dispute note the amount, the reason and the **Respond by** date.
5. **Compare and write**: Run the Balance summary again for the day before and for the same weekday last week, then report gross, refunds, net, fees, the number of payments, new paying customers with their plans, the largest payment and any dispute.

Note: The Balance summary report only shows complete days and fills in by 12:00 PM the following day in the report's time zone, so a 7:00 run usually has to use the Payments page, where amounts are in the charge currency and refunds of older payments show under the original payment. Checking each customer's history by hand is slow past a few dozen payments a day.

## The report

- **Gross revenue** yesterday, against the day before and the same weekday last week.
- **Refunds** and **net** after refunds, plus Stripe fees.
- **New paying customers**: how many, and on which plans.
- The largest payment of the day, and any dispute opened, with its reason and response deadline.

## 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-daily-revenue/<date of this run, e.g. 2026-10-16>",
  "item_key": "stripe-daily-revenue",
  "project": "Acme",
  "source": "Stripe daily revenue report skill",
  "kind": "metric",
  "title": "Yesterday: $3,486 gross, 7 new paying customers",
  "metric": {
    "label": "Gross revenue",
    "value": 3486,
    "prefix": "$",
    "better": "higher",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "Refunds",
            "value": 129,
            "prefix": "$",
            "better": "lower"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Net",
            "value": 3357,
            "prefix": "$"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "New paying customers",
            "value": 7
          }
        }
      ]
    }
  ],
  "widget": [
    {
      "type": "KeyValue",
      "props": {
        "items": [
          {
            "key": "Successful charges",
            "value": "41"
          },
          {
            "key": "Refunds",
            "value": "2, $129.00"
          },
          {
            "key": "Net after refunds",
            "value": "$3,357.00"
          },
          {
            "key": "Stripe fees",
            "value": "$113.39"
          },
          {
            "key": "New paying customers",
            "value": "7 (5 Starter, 2 Team)"
          },
          {
            "key": "Largest payment",
            "value": "$948.00, Team annual"
          },
          {
            "key": "Disputes opened",
            "value": "None"
          }
        ]
      }
    }
  ],
  "size": "md"
}
JSON
```

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

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

Suggested: Every day at 7:00 (`0 7 * * *`). From cron, with the agent signed in on that machine:

```bash
0 7 * * * claude -p "Run the stripe-daily-revenue 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-daily-revenue#schedule

Source: https://briefkin.dev/skills/stripe-daily-revenue
