Polar
Connect a Polar organization to SaaS Pro Max for read-only revenue analytics. The connector reads customers, subscriptions and orders, and keeps them current with Standard Webhooks deliveries. It never writes to Polar.
See the revenue module for how the numbers are derived.
1. Create an organization access token
Polar dashboard → Settings → Developers → New token. Read scopes are enough:
customers:read
subscriptions:read
orders:read
products:read
The token looks like polar_oat_…. Sandbox tokens are issued from
sandbox.polar.sh and are only valid against the sandbox API.
2. Add the connector
In the console: Revenue → Connectors → Add a connector.
- Provider: Polar
- API key: the organization access token
- Organization id: the UUID of the Polar organization, which scopes every list request. Find it in Settings → General.
- Reporting currency: the currency the dashboard totals in
Creating a connector requires revenue.write and a passkey verified in the last
ten minutes. The token 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/polar/<connectorId>?t=<token>
3. Create the webhook endpoint
Polar dashboard → Settings → Webhooks → Add endpoint. Paste the URL, choose the Raw format (Slack and Discord formats are for humans, not for ingest), and select:
customer.created
customer.updated
subscription.created
subscription.active
subscription.updated
subscription.canceled
subscription.revoked
subscription.past_due
subscription.paused
subscription.resumed
subscription.uncanceled
subscription.cycled
order.created
order.paid
order.updated
order.refunded
Copy the endpoint secret shown once at creation and paste it into the connector's Replace webhook secret field.
Polar signs with Standard Webhooks:
webhook-id, webhook-timestamp and webhook-signature headers, HMAC-SHA256
over id.timestamp.body, base64, five-minute tolerance. Polar keys the HMAC with
the UTF-8 bytes of the secret exactly as issued rather than the base64 form the
specification describes; SaaS Pro Max tries both, so either encoding verifies.
The webhook-id header is also the idempotency key — Polar's payload carries no
event id of its own, and that header is covered by the signature.
4. Backfill
Adding a connector enqueues a sync immediately. It pages
/v1/customers, /v1/subscriptions and /v1/orders with page and limit
until pagination.max_page, scoped by organization_id. The hourly job then
re-reads from the last successful sync minus one day, and Sync now runs one
on demand.
Set Sandbox on the connector to read https://sandbox-api.polar.sh instead
of production.
Testing the connection
Polar can replay a delivery from Settings → Webhooks → your endpoint → Deliveries, which is the quickest end-to-end check. Locally, forward the endpoint to your machine with a tunnel and create a test subscription in the sandbox.
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 the
secret and that the URL still carries its ?t= token.
What the connector reads
| Polar object | Becomes |
|---|---|
| Customer | revenue_customers (email, name), linked to a person by email |
| Subscription | revenue_subscriptions; recurring_interval and recurring_interval_count drive the monthly normalization |
| Order | revenue_payments at the gross total_amount, with refunded_amount as refunded_cents |
A subscription.revoked event that is not already canceled is stored as
expired, which is what a revoked benefit means for revenue: access stopped, MRR
goes to zero.