//Payment Webhooks

Payment Webhook Setup

ButtrBase treats payment provider webhooks as the source of truth for subscription and invoice state.

Active Endpoints

  • POST /api/billing/webhooks/stripe
  • POST /api/billing/webhooks/paypal
  • Required Environment Variables

    Stripe

    ~~~env STRIPE_SECRET_KEY=sk_live_or_test_... STRIPE_PUBLISHABLE_KEY=pk_live_or_test_... STRIPE_WEBHOOK_SECRET=whsec_... ~~~

    PayPal

    ~~~env PAYPAL_CLIENT_ID=... PAYPAL_SECRET=... PAYPAL_ENV=sandbox PAYPAL_WEBHOOK_ID_SANDBOX=... PAYPAL_WEBHOOK_ID_LIVE=... ~~~

    Legacy PayPal routes in the monolith still read PAY_PAL_ID and PAY_PAL_SECRET. Keep them aligned until those routes are retired.

    Stripe Events

    Subscribe at minimum to:

  • checkout.session.completed
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.paid
  • invoice.payment_failed
  • charge.refunded
  • refund.created
  • refund.updated
  • charge.dispute.created
  • charge.dispute.updated
  • charge.dispute.closed
  • PayPal Events

    Subscribe at minimum to:

  • BILLING.SUBSCRIPTION.CREATED
  • BILLING.SUBSCRIPTION.ACTIVATED
  • BILLING.SUBSCRIPTION.CANCELLED
  • BILLING.SUBSCRIPTION.EXPIRED
  • BILLING.SUBSCRIPTION.SUSPENDED
  • BILLING.SUBSCRIPTION.PAYMENT.COMPLETED
  • BILLING.SUBSCRIPTION.PAYMENT.FAILED
  • PAYMENT.SALE.COMPLETED
  • PAYMENT.SALE.DENIED
  • PAYMENT.SALE.REFUNDED
  • PAYMENT.CAPTURE.COMPLETED
  • PAYMENT.CAPTURE.DENIED
  • PAYMENT.CAPTURE.REFUNDED
  • PAYMENT.CAPTURE.REVERSED
  • CUSTOMER.DISPUTE.CREATED
  • CUSTOMER.DISPUTE.UPDATED
  • CUSTOMER.DISPUTE.RESOLVED

Operational Rule

Do not mark a payment paid from a redirect or return URL. Wait for the provider webhook, then read billing state back through GET /api/billing/history.