Documentation menu

Stripe

Connect a Stripe account to SaaS Pro Max for read-only revenue analytics. The connector reads customers, subscriptions, charges and invoices, and keeps them current with signed webhooks. It never writes to Stripe.

See the revenue module for how the numbers are derived.

1. Create a restricted API key

Stripe Dashboard → Developers → API keys → Restricted keys → Create restricted key. Read-only is enough:

Resource Permission
Customers Read
Subscriptions Read
Charges Read
Invoices Read

The key looks like rk_live_… (rk_test_… in a sandbox). A standard secret key (sk_live_…) also works, but a restricted key is what you want: this integration only ever reads.

If your subscriptions live in a connected account, create the key on the platform account and put the account id (acct_…) in the connector's Connected account id field. Every request is then sent with Stripe-Account.

2. Add the connector

In the console: Revenue → Connectors → Add a connector.

  • Provider: Stripe
  • Label: whatever names this account for your team
  • API key: the restricted key from step 1
  • Webhook secret: leave this until step 3, or paste a placeholder and edit it after — you need the URL first
  • Reporting currency: the currency the dashboard totals in

Creating a connector requires revenue.write and a passkey verified in the last ten minutes. The key is envelope-encrypted into the vault immediately and is never shown again.

The connector list then shows the webhook URL:

https://<your host>/api/v1/webhooks/stripe/<connectorId>?t=<token>

3. Create the webhook endpoint

Stripe Dashboard → Developers → Webhooks → Add endpoint, paste the URL, and select these events:

customer.created
customer.updated
customer.subscription.created
customer.subscription.updated
customer.subscription.deleted
customer.subscription.paused
customer.subscription.resumed
charge.succeeded
charge.refunded
charge.failed
invoice.paid

Listening to more than you need only adds load; nothing else is read.

Reveal the endpoint's signing secret (whsec_…) and paste it into the connector's Replace webhook secret field (Revenue → Connectors → Edit). Rolling the secret later is safe: Stripe signs with both for up to 24 hours and verification accepts either.

4. Backfill

Adding a connector enqueues a sync immediately; it walks the last 24 months. After that the hourly revenue.sync job re-reads from the last successful sync minus one day. Sync now on the connector runs one on demand.

Testing the connection

With the Stripe CLI:

stripe listen --forward-to "https://<your host>/api/v1/webhooks/stripe/<connectorId>?t=<token>"
stripe trigger customer.subscription.created

stripe listen prints its own signing secret, which is different from the dashboard endpoint's. Use whichever one matches the deliveries you are testing.

Deliveries appear under Recent event on the connector, with the error message when one fails. A 401 there means the signature did not verify: check that the secret matches the endpoint and that the URL still carries its ?t= token.

What the connector reads

Stripe object Becomes
Customer revenue_customers (email, name), linked to a person by email
Subscription revenue_subscriptions with the normalized monthly value
Charge revenue_payments, keyed on the payment intent, amount_refunded carried as refunded_cents
Invoice The same payment as its charge — both resolve to the payment intent, so revenue is never counted twice

Subscription period ends are read from items.data[].current_period_end as well as the subscription itself, so both the pre- and post-2025-03-31 (Basil) API shapes work and no API version is pinned.

Trial subscriptions are stored as trialing and contribute no MRR until they convert.