docs/content/docs/plugins/commet.mdx
Commet is a Merchant of Record that handles subscriptions, usage-based billing, feature gating, taxes and global payments. This plugin integrates Commet with Better Auth, connecting your authentication layer to billing and feature access through a composable set of sub-plugins.
<Callout> This plugin is maintained by the Commet team. For bugs, issues or feature requests, please visit the [Commet GitHub repo](https://github.com/commet-labs/commet). </Callout>better-auth @commet/better-auth @commet/node
Get your API key from the Commet dashboard and add it to your environment.
COMMET_API_KEY=ck_...
The Commet plugin comes with a set of sub-plugins that add functionality to your stack. Add only the ones you need.
import { betterAuth } from "better-auth";
import {
commet,
portal,
subscriptions,
features,
usage,
seats,
} from "@commet/better-auth";
import { Commet } from "@commet/node";
const commetClient = new Commet({
apiKey: process.env.COMMET_API_KEY!,
});
export const auth = betterAuth({
// ... Better Auth config
plugins: [
commet({
client: commetClient,
createCustomerOnSignUp: true,
use: [
portal({ returnUrl: "/dashboard" }),
subscriptions(),
features(),
usage(),
seats(),
],
}),
],
});
You will use the Better Auth client to interact with the Commet functionalities.
import { createAuthClient } from "better-auth/react";
import { commetClient } from "@commet/better-auth/client";
export const authClient = createAuthClient({
plugins: [commetClient()],
});
commet({
client: commetClient,
createCustomerOnSignUp: true,
getCustomerCreateParams: ({ user }) => ({
fullName: user.name,
metadata: { source: "signup" },
}),
use: [
// Commet sub-plugins
],
});
client: Commet SDK client instanceuse: Array of Commet sub-plugins (at least one)createCustomerOnSignUp: Automatically create a Commet customer when a user signs upgetCustomerCreateParams: Custom function to provide additional customer creation parameters (fullName, domain, metadata)When createCustomerOnSignUp is enabled, a Commet customer is automatically created when a new user signs up. The customer is created with its id set to the Better Auth user ID, so you don't need any mapping between your users and Commet customers.
Redirects customers to the Commet customer portal for self-service billing management.
import { commet, portal } from "@commet/better-auth";
commet({
client: commetClient,
use: [portal({ returnUrl: "/dashboard" })],
});
The portal plugin adds a portal method scoped under authClient.customer, which redirects the user to the Commet customer portal.
await authClient.customer.portal();
returnUrl: URL to return to after the customer leaves the portalGet and cancel the authenticated user's subscription.
import { commet, subscriptions } from "@commet/better-auth";
commet({
client: commetClient,
use: [subscriptions()],
});
// Get the current subscription
const { data: subscription } = await authClient.subscription.get();
// Cancel the subscription
await authClient.subscription.cancel({
reason: "Too expensive",
immediate: false, // Cancel at the end of the billing period
});
The cancel method accepts an optional reason and an immediate flag. By default, cancellation takes effect at the end of the current billing period.
Check feature access for the authenticated user. Supports boolean, metered and seat-based features.
import { commet, features } from "@commet/better-auth";
commet({
client: commetClient,
use: [features()],
});
// List all features
const { data: features } = await authClient.features.list();
// Get a specific feature
const { data: feature } = await authClient.features.get("api_calls");
// Check if a boolean feature is enabled
const { data: check } = await authClient.features.check("sso");
// { allowed: boolean }
// Check if the user can use one more unit of a metered feature
const { data: canUse } = await authClient.features.canUse("api_calls");
// { allowed: boolean, willBeCharged: boolean }
Track usage events for metered billing.
import { commet, usage } from "@commet/better-auth";
commet({
client: commetClient,
use: [usage()],
});
await authClient.usage.track({
feature: "api_calls",
value: 1,
idempotencyKey: "evt_123",
properties: { endpoint: "/api/generate" },
});
The authenticated user is automatically associated with the event. The feature field maps to a feature code in your Commet plan.
Manage seat-based licenses for the authenticated user.
import { commet, seats } from "@commet/better-auth";
commet({
client: commetClient,
use: [seats()],
});
// List all seat balances
const { data: seatBalances } = await authClient.seats.list();
// Add seats
await authClient.seats.add({ featureCode: "member", count: 5 });
// Remove seats
await authClient.seats.remove({ featureCode: "member", count: 2 });
// Set an exact count
await authClient.seats.set({ featureCode: "admin", count: 3 });
// Set multiple seat types at once
await authClient.seats.setAll({ admin: 2, member: 10, viewer: 50 });
Handle Commet webhooks with signature verification. Webhooks are optional — you can always query the current state through the other sub-plugins.
import { commet, webhooks } from "@commet/better-auth";
commet({
client: commetClient,
use: [
webhooks({
secret: process.env.COMMET_WEBHOOK_SECRET!,
onSubscriptionActivated: (payload) => {},
onSubscriptionCanceled: (payload) => {},
onPaymentReceived: (payload) => {},
onPayload: (payload) => {}, // Catch-all
}),
],
});
Configure a webhook endpoint in your Commet dashboard pointing to /api/auth/commet/webhooks, and add the signing secret to your environment.
COMMET_WEBHOOK_SECRET=whsec_...
The plugin supports handlers for all Commet webhook events:
onPayload — Catch-all handler for any incoming eventonSubscriptionCreated — Triggered when a subscription is createdonSubscriptionActivated — Triggered when a subscription becomes activeonSubscriptionCanceled — Triggered when a subscription is canceledonSubscriptionUpdated — Triggered when a subscription is updatedonSubscriptionPlanChanged — Triggered when a subscription changes planonPaymentReceived — Triggered when a payment is receivedonPaymentFailed — Triggered when a payment failsonInvoiceCreated — Triggered when an invoice is created