Documentation menu

RevenueCat

Connect a RevenueCat project to SaaS Pro Max for read-only revenue analytics across the App Store, Play Store, Stripe and web billing. The connector reads customers and subscriptions through the v2 API and keeps them current with webhooks. It never writes to RevenueCat.

See the revenue module for how the numbers are derived.

1. Create a secret API key

RevenueCat dashboard → Project settings → API keys → New API key. It needs read access to customers and subscriptions; the key looks like sk_….

Note the project id (proj…) from Project settings → General. Every v2 request is scoped to a project, so the connector cannot sync without it.

2. Add the connector

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

  • Provider: RevenueCat
  • API key: the secret key from step 1
  • Project id: required
  • Webhook secret: the value you will configure as the Authorization header in step 3 — pick a long random string, for example openssl rand -base64 32
  • Reporting currency: the currency the dashboard totals in

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

The connector list then shows the webhook URL:

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

3. Configure the webhook

RevenueCat dashboard → Project settings → Integrations → Webhooks:

  • Webhook URL: the URL above
  • Authorization header value: exactly the webhook secret you stored in step 2
  • Event types: all subscription events. At minimum INITIAL_PURCHASE, RENEWAL, CANCELLATION, UNCANCELLATION, EXPIRATION, BILLING_ISSUE, PRODUCT_CHANGE, SUBSCRIPTION_PAUSED and NON_RENEWING_PURCHASE.

RevenueCat does not sign its webhooks: it sends the Authorization header value back verbatim on every request, and SaaS Pro Max compares it against the stored secret in constant time. Treat that value as a password — anyone who has it can post events. Rotate it by editing the connector and the RevenueCat integration together.

Send the built-in Test event from the dashboard to check the wiring; it is accepted, verified and then deliberately ignored, so it never adds a row.

4. Backfill

Adding a connector enqueues a sync immediately. It pages /v2/projects/<projectId>/customers and /v2/projects/<projectId>/subscriptions by following next_page. The hourly job re-runs it, and Sync now runs one on demand.

What the connector reads

RevenueCat field Becomes
app_user_id The billing customer; subscriber_attributes.$email supplies the email that links it to a person
original_transaction_id The subscription identity, so a year of renewals is one subscription rather than twelve
transaction_id One payment per purchase or renewal
price_in_purchased_currency + currency The payment amount; price (USD) is the fallback
period_type = TRIAL Stored as trialing, contributing no MRR until it converts

Inferred billing intervals

RevenueCat does not report a billing interval, so it is inferred from the length of the purchased period (purchased_at_msexpiration_at_ms):

Period Interval
≤ 2 days daily
≤ 10 days weekly
≤ 45 days monthly
≤ 75 / 135 / 225 days 2, 3 or 6 monthly
≤ 400 days yearly
≤ 800 days 2 yearly
longer, or no expiry lifetime — no MRR, counted in payments

The windows are wide enough to absorb store drift: a "monthly" App Store period is 30 or 31 days and a yearly one 365 or 366.

NON_RENEWING_PURCHASE is always treated as a one-off: it produces a payment and no MRR.

A CANCELLATION means auto-renew was switched off — the subscription is marked canceled at that moment. When its reason is CUSTOMER_SUPPORT it is also recorded as a refund against the original transaction, which is how RevenueCat reports support-issued refunds.