Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.usepaykit.dev/llms.txt

Use this file to discover all available pages before exploring further.

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
  })
  .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.canceledPayment
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>