Skip to main content
PayKit normalizes webhook events into a consistent set of typed events across all providers.

Setup

const webhook = paykit.webhooks
  .setup({ webhookSecret: process.env.YOUR_WEBHOOK_SECRET! })
  .on('customer.created', async event => {
    // event.data is typed as Customer
  })
  .on('subscription.created', async event => {
    // event.data is typed as Subscription
  })
  .on('payment.created', async event => {
    // event.data is typed as Payment — payment initiated
  })
  .on('payment.succeeded', async event => {
    // event.data is typed as Payment — payment completed successfully
  })
  .on('payment.failed', async event => {
    // event.data is typed as Payment — payment failed or was canceled
  })
  .on('refund.created', async event => {
    // event.data is typed as Refund
  })
  .on('invoice.generated', async event => {
    // event.data is typed as Invoice
  });

await webhook.handle({
  body: rawBody,
  headersAsObject: Object.fromEntries(request.headers),
  fullUrl: request.url,
});

Standard events

EventData type
customer.createdCustomer
customer.updatedCustomer
customer.deletedCustomer
subscription.createdSubscription
subscription.updatedSubscription
subscription.canceledSubscription
payment.createdPayment
payment.updatedPayment
payment.succeededPayment
payment.failedPayment
refund.createdRefund
invoice.generatedInvoice

Raw provider events

You can also listen to native provider events directly. These are prefixed with the provider name and fully typed:
// Stripe — typed as Stripe.Checkout.Session
.on('stripe.checkout.session.completed', async event => {
  console.log(event.data.payment_intent);
})

// Paystack — typed as PaystackTransaction
.on('paystack.charge.success', async event => {
  console.log(event.data.reference);
})
Standard events and raw events can be mixed freely on the same webhook instance.

headersAsObject

webhook.handle expects headersAsObject as a plain Record<string, string>. Convert from your framework’s headers object using Object.fromEntries:
// Web Request (Next.js, Hono, etc.)
headersAsObject: Object.fromEntries(request.headers);

// Express
headersAsObject: req.headers as Record<string, string>;