Documentation menu

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.