Polar payments
Subscription billing with Polar.
Polar is an open-source funding platform for developers. The KavachOS plugin wires Polar checkout sessions and subscription webhooks to your user records — no Polar SDK required.
Setup
Get your credentials
From your Polar dashboard, go to Settings → API and create an access token. Under Webhooks, create an endpoint pointing to /api/kavach/auth/polar/webhook and copy the signing secret.
Configure the plugin
import { createKavach } from 'kavachos';
import { polar } from 'kavachos/auth';
const kavach = await createKavach({
database: { provider: 'postgres', url: process.env.DATABASE_URL },
plugins: [
polar({
accessToken: process.env.POLAR_ACCESS_TOKEN,
webhookSecret: process.env.POLAR_WEBHOOK_SECRET,
sandbox: process.env.NODE_ENV !== 'production',
onSubscriptionChange: async (userId, sub) => {
console.log(`User ${userId}: ${sub.status}`);
},
}),
],
});Usage
Create a checkout session
// From an authenticated endpoint
const { url } = await kavach.plugins.polar.createCheckout(userId, 'product_xxx', {
successUrl: 'https://example.com/success',
});
// Redirect the user
redirect(url);Check subscription status
const sub = await kavach.plugins.polar.getSubscription(userId);
if (sub?.status === 'active') {
// grant access
}HTTP endpoints
The plugin registers three routes under your KavachOS base path.
POST /auth/polar/checkout
Creates a checkout session. Requires an authenticated session.
// Request body
{ "productId": "product_xxx", "successUrl": "https://example.com/success" }
// Response
{ "url": "https://buy.polar.sh/...", "id": "checkout_xxx" }GET /auth/polar/subscription
Returns the current subscription for the authenticated user.
{
"subscription": {
"id": "sub_xxx",
"status": "active",
"productId": "product_xxx",
"currentPeriodEnd": "2025-12-31T00:00:00.000Z",
"cancelAtPeriodEnd": false
}
}Returns { "subscription": null } when the user has no active subscription.
POST /auth/polar/webhook
Receives webhook events from Polar. Signature is verified with HMAC-SHA256 — no session auth needed.
Handled events:
| Event | Action |
|---|---|
subscription.created | Links customer, stores subscription |
subscription.updated | Updates status and period end |
subscription.revoked | Clears subscription, fires callback |
Sandbox mode
Set sandbox: true to point at sandbox.api.polar.sh during development. Polar's sandbox environment mirrors the production API and lets you test webhooks without real payments.
polar({
accessToken: process.env.POLAR_SANDBOX_TOKEN,
webhookSecret: process.env.POLAR_SANDBOX_WEBHOOK_SECRET,
sandbox: true,
})Reference
PolarConfig
| Field | Type | Description |
|---|---|---|
accessToken | string | Polar API access token |
webhookSecret | string | Webhook signing secret for HMAC verification |
organizationId | string? | Scope checkouts to a specific organization |
sandbox | boolean? | Use sandbox environment (default: false) |
onSubscriptionChange | function? | Called whenever subscription status changes |
PolarSubscription
| Field | Type | Description |
|---|---|---|
id | string | Polar subscription ID |
status | string | active, canceled, trialing, past_due, etc. |
productId | string | Polar product ID |
currentPeriodEnd | Date | When the current billing period ends |
cancelAtPeriodEnd | boolean | Whether cancellation is scheduled |
KavachOS stores Polar subscription data in the kavach_users table. You can query it directly with Drizzle or any SQL client.