NimBuild Docs

Webhooks

How Stripe webhooks are processed.

Endpoint

POST /api/payments/stripe/webhook

Security

Signature Verification

Every webhook is verified with Stripe's official webhook helper:

const event = constructStripeWebhookEvent(rawBody, signature);

The signature is in the stripe-signature header. constructStripeWebhookEvent() wraps stripe.webhooks.constructEvent(...) and uses STRIPE_WEBHOOK_SECRET.

Idempotency

Duplicate webhooks are handled by checking providerPaymentId in the payment table. If a payment with the same ID already exists, the webhook is acknowledged without re-processing.

Supported Events

EventAction
checkout.session.completedCreate payment, grant credits, send email
invoice.paidProcess subscription renewal payment
customer.subscription.createdMark subscription active when applicable
customer.subscription.updatedMark subscription active when applicable
customer.subscription.deletedMark subscription canceled

Setup

In your Stripe Dashboard, set the webhook URL to:

https://your-domain.com/api/payments/stripe/webhook

And configure the webhook secret in .env:

STRIPE_WEBHOOK_SECRET="whsec_your_secret"

Debugging

If webhooks aren't working:

  1. Check Stripe Dashboard webhook logs for delivery status
  2. Verify STRIPE_WEBHOOK_SECRET matches your Stripe settings
  3. Ensure the endpoint is publicly accessible (not behind auth)
  4. Check server logs for signature verification errors

On this page