Introduction
Receive real-time notifications when events happen in your Commet account.
Webhooks let your application receive real-time HTTP notifications when events happen in Commet — like a subscription being activated, a payment failing, or an invoice being created.
How it works
- You register an endpoint URL in the Commet dashboard
- You select which events you want to receive
- When an event occurs, Commet sends a
POSTrequest to your URL with the event data
Payload structure
Every webhook delivers a JSON payload with this envelope:
{
"event": "subscription.activated",
"timestamp": "2026-03-25T14:30:00.000Z",
"organizationId": "org_abc123",
"data": {
// Event-specific fields
}
}| Field | Type | Description |
|---|---|---|
event | string | The event type (e.g. subscription.activated) |
timestamp | string | ISO 8601 datetime when the event was emitted |
organizationId | string | Your organization ID |
data | object | Event-specific payload — see Webhook Events |
Handling webhooks with Next.js
The @commet/next package provides a handler that verifies signatures and routes events automatically.
import { Webhooks } from "@commet/next";
export const POST = Webhooks({
webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,
onSubscriptionActivated: async (payload) => {
// Grant access to your product
await db.update(users)
.set({ isPaid: true })
.where(eq(users.id, payload.data.customerId));
},
onSubscriptionCanceled: async (payload) => {
// Revoke access
await db.update(users)
.set({ isPaid: false })
.where(eq(users.id, payload.data.customerId));
},
// Catch-all for events without a specific handler
onPayload: async (payload) => {
console.log(`Received: ${payload.event}`);
},
});Verifying signatures manually
If you're not using @commet/next, verify the HMAC-SHA256 signature yourself using @commet/node:
import { Commet } from "@commet/node";
const commet = new Commet({ apiKey: process.env.COMMET_API_KEY! });
export async function POST(request: Request) {
const rawBody = await request.text();
const signature = request.headers.get("x-commet-signature");
const payload = commet.webhooks.verifyAndParse({
rawBody,
signature,
secret: process.env.COMMET_WEBHOOK_SECRET!,
});
if (!payload) {
return new Response("Invalid signature", { status: 403 });
}
// Handle the event
switch (payload.event) {
case "subscription.activated":
// Grant access
break;
case "subscription.canceled":
// Revoke access
break;
}
return new Response("OK", { status: 200 });
}Headers
Commet sends these headers with every webhook request:
| Header | Description |
|---|---|
X-Commet-Signature | HMAC-SHA256 hex signature of the raw body |
X-Commet-Event | The event type (e.g. subscription.activated) |
X-Commet-Timestamp | ISO 8601 datetime when the event was emitted |
Content-Type | application/json |
Retry policy
If your endpoint returns a non-2xx status or times out (10 seconds), Commet retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 15 minutes |
| 4th retry | 30 minutes |
| 5th retry | 1 hour |
| 6th retry | 2 hours |
| 7th retry | 4 hours |
| 8th retry | 6 hours |
After 8 failed attempts, the delivery is marked as failed. You can monitor delivery status in the Commet dashboard.
Related
- Webhook Events — all events and their payloads
How is this guide?