Polar setup
Keylight integrates with Polar through Standard Webhooks: every paid order, subscription state change, and successful refund hits Keylight, and Keylight mints, renews, or refunds the matching license. There’s no OAuth and no outbound Polar API call from Keylight — only the signed webhook with a shared HMAC secret.
1. Enable Polar in the dashboard
Section titled “1. Enable Polar in the dashboard”From your dashboard, go to Settings → Integrations → Polar and click Enable Polar. Keylight reveals the webhook URL:
https://api.keylight.dev/webhooks/polar/<your-tenant-id>Copy it — you’ll paste it into Polar’s webhook settings in step 3.
2. Map Polar Product IDs to Keylight apps
Section titled “2. Map Polar Product IDs to Keylight apps”In Settings → Integrations → Polar, add one row per product.
| Polar Product ID | Keylight app | Key type |
|---|---|---|
prod_abc… | myapp | pro |
prod_xyz… | myapp | team |
Keylight reads data.productId from each event to pick the row. Unmapped products are rejected with 400 unmapped_product instead of being minted against an unknown app.
3. Configure the webhook in Polar
Section titled “3. Configure the webhook in Polar”In the Polar dashboard:
- Go to Settings → Webhooks → Add Endpoint.
- Paste the Keylight URL from step 1 into URL.
- Set Format to Raw.
- Subscribe to these events:
order.createdorder.refunded(deliberately skip — Polar fires both this andrefund.created; Keylight only acts on the latter to avoid double-counting)subscription.createdsubscription.updatedsubscription.activesubscription.canceledsubscription.revokedrefund.created
- Save. Polar reveals the signing secret (it starts with
whsec_…) — copy the entire string including the prefix.
Back in Keylight (Settings → Integrations → Polar), paste the secret into Webhook signing secret and save.
4. Test the connection
Section titled “4. Test the connection”Polar’s webhook page has a Send test event action.
- A
200 OKfrom Keylight with a fresh license record in Dashboard → Licenses means signature + product map are correct. 400 invalid_signature→ either the secret is wrong, or thewebhook-id/webhook-timestampheaders were stripped by a proxy in front of Keylight.400 unmapped_product→ the test event’s Product ID isn’t in your map.
What happens on a real sale
Section titled “What happens on a real sale”When a customer checks out, Polar fires order.created with data.status === 'paid'. Keylight verifies the Standard Webhooks signature, looks up the app+key-type from data.productId, mints a license, and records the payment. Subscription renewals arrive as subscription.updated with data.status === 'active' and re-extend the license. subscription.canceled and subscription.revoked flip it to cancelled. A successful refund.created (where data.status === 'succeeded') flips the license to refunded.
Upgrades
Section titled “Upgrades”To send a customer to a Polar checkout that upgrades their existing license, append customer_metadata[keylight_upgrade_key]=<license-key> to the Upgrade checkout URL you set on the key type. Polar echoes the metadata back in the order event and Keylight links the new order to the existing license.
Disconnecting
Section titled “Disconnecting”Settings → Integrations → Polar → Disconnect clears the signing secret and the product map. Existing licenses are untouched — only new webhook deliveries stop minting.