Revenue from Stripe
Nordva Launch can read your own Stripe account and report the numbers a small product needs: MRR, who started paying, who cancelled, and what was collected. The same connection lets Contacts show who became a customer and Attribution show which signup sources produce customers.
Launch only reads. It never creates, changes or refunds anything in your Stripe account, and it never sees card data.
1. Create a restricted key in Stripe
Section titled “1. Create a restricted key in Stripe”In Stripe, go to Developers → API keys → Create restricted key.
Stripe first asks how you will use the key. Choose the option for providing the key to another website, and enter:
| Field | Value |
|---|---|
| Name | Nordva Launch |
| URL | https://launch.nordva.dev |
Then set these five resources to Read and leave everything else at None. Do not pick Write anywhere:
| Resource | Why |
|---|---|
| Customers | Email, name, and your user id from metadata |
| Subscriptions | Status, amount, plan |
| Invoices | Paid invoices, for revenue |
| Products | Plan names |
| Events | The change feed Launch uses to stay up to date |
The key starts with rk_live_. A key starting with rk_test_ connects a test-mode account, which is a good way to try this first.
2. Connect it in the dashboard
Section titled “2. Connect it in the dashboard”Open Revenue in the dashboard and paste the key. Launch checks each of the five permissions before saving and, if one is missing, shows Stripe’s own message naming it.
Connecting is only possible in the dashboard, behind your login. There is no API-key endpoint and no MCP tool for it, so a payment-account credential never travels through an API key or an AI conversation.
The first import starts immediately and runs in the background. After that, each connection syncs about once an hour.
Optional: link your own user ids
Section titled “Optional: link your own user ids”If your Stripe customers carry your application’s user id in metadata (for example metadata.user_id), enter that key name when connecting. Feedback and notifications you send with the same user_id then appear on the right person in Contacts.
3. Read the numbers
Section titled “3. Read the numbers”All amounts are in the smallest currency unit (cents), reported per currency, and never converted or added together.
curl "https://api.nordva.dev/v1/revenue/summary?period_days=30" \ -H "Authorization: Bearer nv_live_YOUR_SECRET_KEY"{ "data": { "period_days": 30, "by_currency": [{ "currency": "usd", "mrr_minor": 38000, "active_subscriptions": 21, "trialing_subscriptions": 2, "paying_customers": 20, "new_subscriptions": 4, "new_mrr_minor": 7300, "churned_subscriptions": 1, "churned_mrr_minor": 1500, "net_mrr_change_minor": 5800, "revenue_minor": 41200, "payments": 23 }], "sync": { "status": "active", "last_synced_at": "2026-09-17T14:02:11.000Z", "livemode": true } }}| Endpoint | What it returns |
|---|---|
GET /v1/integrations/stripe | Connection status, last sync, synced counts, last error |
GET /v1/revenue/summary?period_days= | The summary above |
GET /v1/revenue/series?range=30d|90d|12m|all | Collected revenue per day (up to 90 days), ISO week (up to a year) or month, with empty buckets filled with zero |
GET /v1/revenue/events?type=payment|cancellation&limit= | Recent payments and cancellations with customer email and plan. For a cancellation, amount_minor is the monthly amount that stopped |
History reaches 90 days on Indie and 24 months on Builder. A longer range is shortened and the response says so with clamped_to_plan: true.
What MRR means here
Section titled “What MRR means here”MRR is an operational number, not an accounting one:
- Yearly plans are divided by twelve, weekly plans multiplied by 52 ÷ 12, and quantities are included.
- A coupon counts when it is
forever, orrepeatingand still running. Aoncecoupon does not change the run rate. - Metered and tiered prices have no fixed amount and count as zero. A subscription with paused collection counts as zero.
activeandpast_duesubscriptions count. Trialing subscriptions are reported separately.- Revenue is paid invoices. Refunds are not subtracted.
Sync status
Section titled “Sync status”Every response includes sync:
status | Meaning |
|---|---|
backfilling | The first import is still running. Numbers are incomplete. |
active | Up to date as of last_synced_at. |
revoked | Stripe no longer accepts the key (deleted or rolled). Numbers are as of the last sync. Disconnect and connect a new key. Launch emails the account owner when this happens. |
error | The key lost a read permission. last_error on the status endpoint names it. |
Disconnecting
Section titled “Disconnecting”Disconnect in the dashboard deletes the stored key and every synced customer, subscription and invoice. Nothing changes in Stripe. Deleting the project does the same.
From an MCP client
Section titled “From an MCP client”Ask your assistant things like “what’s my MRR and did it grow this month?” or “who cancelled this week?”. It uses get_revenue_summary, get_revenue_series, list_recent_payments and get_stripe_connection_status. The assistant cannot connect Stripe and will never ask you for a key.
Errors
Section titled “Errors”| Code | Meaning |
|---|---|
STRIPE_NOT_CONNECTED | No Stripe account is connected to this project. |
STRIPE_KEY_NOT_RESTRICTED | The pasted key is not an rk_ key. If it was a secret key, roll it. |
STRIPE_KEY_INVALID | Stripe did not recognise the key. |
STRIPE_KEY_MISSING_PERMISSION | One of the five read permissions is missing. The message names it. |
STRIPE_ALREADY_CONNECTED | Disconnect the current key first. |
STRIPE_CONNECTION_LIMIT_REACHED | Indie includes one connection per account. Builder includes one per project. |