From commet
Integrate Commet billing and payments into any application. Use when working with @commet/node, @commet/next, @commet/better-auth, the Commet CLI, or building billing features like subscriptions, usage tracking, seat management, checkout, customer portal, webhooks, feature gating, or payment flows. Triggers on imports from "@commet/node", "@commet/next", "@commet/better-auth", commet SDK usage, billing integration tasks, or mentions of Commet.
npx claudepluginhub commet-labs/commet-skills --plugin commetThis skill uses the workspace's default tool permissions.
Commet is an all-in-one billing and payments platform. Merchant of Record handling taxes, compliance, refunds, and payouts. Integrate with a few lines of code.
Integrates Commet billing and payments into Node.js and Next.js apps via @commet/node, @commet/next, @commet/better-auth. Handles subscriptions, usage tracking, seats, checkouts, portals, webhooks, feature gating.
Clerk Billing and Stripe subscription management setup. Use when implementing subscriptions, configuring pricing plans, setting up billing, adding payment flows, managing entitlements, or when user mentions Clerk Billing, Stripe integration, subscription management, pricing tables, payment processing, or monetization.
Implements Stripe payment processing for checkout sessions, subscriptions, webhooks, refunds, and customer management in PCI-compliant flows for web/mobile apps.
Share bugs, ideas, or general feedback.
Commet is an all-in-one billing and payments platform. Merchant of Record handling taxes, compliance, refunds, and payouts. Integrate with a few lines of code.
| Package | Purpose | Install |
|---|---|---|
@commet/node | Core SDK - customers, subscriptions, usage, seats, features, portal, webhooks | npm i @commet/node |
@commet/next | Next.js helpers - webhook handler, customer portal, pricing markdown | npm i @commet/next |
@commet/ai-sdk | Vercel AI SDK middleware - automatic AI token usage billing | npm i @commet/ai-sdk |
@commet/better-auth | Better Auth plugin - auto customer sync, auth-scoped billing | npm i @commet/better-auth |
@commet/cli | CLI - login, link, pull types, scaffold projects from templates | npm i -g @commet/cli |
import { Commet } from "@commet/node";
const commet = new Commet({
apiKey: process.env.COMMET_API_KEY!, // ck_xxx format
environment: "production", // "sandbox" | "production"
});
Sandbox: https://sandbox.commet.co. Production: https://commet.co.
commet login -> commet link -> commet pull (generates .commet/types.d.ts for autocomplete)id = your user IDsubscriptions.create() -> redirect to checkoutUrlsubscriptions.get() to check subscription status (preferred over webhooks)usage.track() for metered features, seats.add/remove/set() for seatsfeatures.check(), features.canUse(), features.get()portal.getUrl() -> redirect for self-service billing managementSee references/sdk.md for the complete API surface of @commet/node.
See references/nextjs.md for @commet/next webhook handlers, customer portal routes, and pricing markdown.
See references/ai-sdk.md for @commet/ai-sdk middleware that auto-tracks AI token usage for billing.
See references/better-auth.md for the @commet/better-auth plugin that auto-syncs customers and provides auth-scoped billing endpoints.
See references/billing-concepts.md for plan structure, feature types, consumption models, and charging behavior.
Always query subscription/feature state directly with the SDK instead of relying on webhooks to sync state. The recommended pattern is to call subscriptions.get(), features.check(), or features.list() when you need to know a customer's status. Webhooks are useful for background tasks (sending emails, provisioning resources) but should never be the source of truth for access control.
// Recommended: query state directly
const { data: sub } = await commet.subscriptions.get("user_123");
if (sub?.status === "active") { /* grant access */ }
// Recommended: feature gating
const { data } = await commet.features.check({ code: "advanced_analytics", customerId: "user_123" });
if (!data?.allowed) { /* show upgrade prompt */ }
Always use customerId (your user/org ID) to identify customers. The SDK accepts both your own IDs and Commet's cus_xxx IDs.
const customer = commet.customer("user_123");
await customer.usage.track("api_calls", 1);
await customer.features.canUse("team_members");
await customer.seats.add("editor");
await customer.subscription.get();
await customer.portal.getUrl();
All POST requests auto-generate idempotency keys. For critical operations, pass explicit keys:
await commet.usage.track({
customerId: "user_123",
feature: "api_calls",
idempotencyKey: `req_${requestId}`,
});
import { CommetAPIError, CommetValidationError } from "@commet/node";
try {
await commet.subscriptions.create({ ... });
} catch (error) {
if (error instanceof CommetValidationError) {
console.log(error.validationErrors); // { field: ["message"] }
}
if (error instanceof CommetAPIError) {
console.log(error.statusCode, error.code);
}
}
COMMET_API_KEY=ck_xxx # API key from dashboard
COMMET_ENVIRONMENT=sandbox # sandbox | production
COMMET_WEBHOOK_SECRET=whsec_xxx # Optional - webhook secret for signature verification