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.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.