Stripe
Connect your Stripe account to track daily Net Revenue, charges/refunds, active subscriptions, and MRR in one place.
Last updated: 2026-05-18
The Stripe integration uses a user-issued Restricted API Key (read-only) to query payment and subscription data. Keys are stored AES-256-GCM encrypted, and full-permission sk_ keys are rejected.
Prerequisites
- A Stripe account (Live or Test mode)
- Permission to create API Keys (Owner / Developer role)
- Starter / Plus / Max plan (revenue alerts are paid features)
Create a Restricted API Key
Open Stripe API Keys
Go to dashboard.stripe.com/apikeys. Scroll to the "Restricted keys" section near the bottom (NOT Standard keys).
Create restricted key
Click "+ Create restricted key".
Choose Third-party application
Select "Providing this key to a third-party application".
Enter app details
Name: Opseer / URL: https://opseer.com
Permissions — Permissions column only
In Customize permissions, ⚠️ use the Permissions column only. Leave the Connect permissions column entirely as None.
Read permissions (12 items)
Core: Balance, Balance Transaction Source, Charges and Refunds, Customers, Disputes, Events, Payment Intents, Payouts, Products
Billing: Invoices, Prices, Subscriptions
Leave all other items AND the entire Connect permissions column as None. Only check Read for these 12 items.
Events permission is required for MRR trend tracking (Yesterday MRR card and MRR Movement chart). Without it, the MRR trend chart will not populate, but daily revenue data continues to collect normally.
Register the key in Opseer
Account or Integrations page
On /dashboard/account (Stripe card) or /dashboard/integrations (account-level area), click Connect.
Paste the key
Paste the Restricted API Key (rk_live_... or rk_test_...) and click Connect.
Auto validation
Opseer validates the prefix (rejects sk_) and dry-runs a Stripe API call (balance retrieve) to confirm the key is valid. Other permissions (Subscriptions, etc.) are required when their respective data is actually fetched. Connection is established immediately on success.
Stripe is connected at the account level, not per project. One connection serves all your projects.
Data collected
Daily time series
balance_transactions are grouped by day to derive:
- Net Revenue (charges minus refunds)
- Charges (count)
- Refunds (count + amount)
- Failed Payments (count)
- Disputes (count)
Point-in-time snapshot
- MRR (Monthly Recurring Revenue, summed from active subscriptions)
- Active Subscriptions (count)
MRR is shown in your Stripe settlement currency. Subscriptions billed in other currencies (e.g. KRW, JPY) are converted to the settlement currency using Stripe's actual payment exchange rates before summing. Usage-based subscriptions are included in total MRR based on their most recent invoice.
MRR movement (daily, cron-based)
Opseer automatically tracks daily MRR changes by polling Stripe subscription events once per day. This populates the Yesterday MRR card and the MRR Trend / MRR Waterfall charts.
- New MRR — new subscriptions created
- Expansion MRR — upgrades (plan price increase)
- Contraction MRR — downgrades (plan price decrease)
- Churned MRR — cancellations / deletions
- Net MRR Movement — sum of the above
- MRR Snapshot — running total carried forward each day
Stripe retains events for 30 days. Opseer backfills up to 30 days automatically on first connect; older history is not available. Events permission (Read) must be enabled on your Restricted API Key.
Cache policy
Page entry reads cache (90-day sliding window) only; no API calls. Clicking Refresh re-fetches the full 90 days and replaces the cache. Stored in revenue_daily_cache with source=stripe.
Daily alert
On /dashboard/alert, toggle Stripe to include yesterday's metrics in the daily "📊 Opseer Revenue Daily Report". The 3 payment channels (Stripe / RevenueCat / Polar) share a unified 5-metric format — MRR / Revenue / Orders / New Subs / Churned with identical labels and ordering.
Security
- Keys starting with sk_ are rejected at input (only rk_ allowed)
- AES-256-GCM encrypted storage (opseer_user_integration.config)
- Decryption requires service_role privileges
- Revoke compromised keys immediately from Stripe Dashboard
Troubleshooting
"INVALID_PREFIX"
You entered a Standard key (pk_ or sk_). Only Restricted Keys (rk_) are allowed.
"AUTH_FAILED"
The key is expired or the balance permission is missing. Note that validation only checks key validity via balance retrieve — a successful connection does not guarantee all other permissions (Subscriptions, etc.) are enabled. Verify all 12 read permissions are checked, then issue a new key.
MRR shows zero
Subscriptions permission is missing, or there are no active subscriptions. Re-check permissions.
Yesterday MRR shows "—"
The MRR movement cron has not run yet (runs once per day), or Events permission is missing from your Restricted API Key. Check that Events → Read is enabled, then wait for the next daily collection (or re-connect to trigger a 30-day backfill).
Disconnect
Click "Disconnect" on the Stripe card (Account or Integrations page). Encrypted key and cache are deleted. Your Stripe account is unaffected; for extra safety, also Revoke the key from Stripe Dashboard.