If local billing work depends on provider callbacks, start here.
Webhook Routes
The application exposes:
/api/payments-providers/stripe/webhook
/api/payments-providers/paddle/webhook
/api/payments-providers/lemon-squeezy/webhook
These paths are release-sensitive integration points.
Stripe local workflow
The most direct local workflow is to use the Stripe CLI to forward events to your local application.
Example:
stripe listen --forward-to localhost:8080/api/payments-providers/stripe/webhook --skip-verify
Adjust the host and port if your app is not running on localhost:8080.
Paddle and Lemon Squeezy local workflow
The repository already ships a Docker Compose setup with an ngrok service. Use it to expose local webhook endpoints for providers that need a public callback URL.
Relevant environment variables from .env.example:
NGROK_AUTHTOKEN=
NGROK_STATIC_DOMAIN=
FORWARD_NGROK_PORT=4040
Typical workflow:
- configure ngrok credentials
- start the Docker Compose stack
- open the ngrok inspector
- point the provider’s sandbox webhook destination at the forwarded public URL
What to verify during local testing
- webhook delivery reaches the expected route
- signature validation succeeds
- transaction records update correctly
- subscription or order state changes are persisted
- related side effects still work with your queue configuration
Common failure modes
- wrong local port
- provider dashboard still pointing at an old ngrok domain
- wrong webhook secret
- queue workers not running when the side effect depends on queued jobs
- long-lived cached config after changing provider credentials
Recommended test matrix
Before release, simulate at least:
- successful checkout
- failed payment
- subscription renewal or equivalent recurring event
- refund or cancellation flow if the provider supports it in your launch scope
Team rule
Do not merge billing changes without replaying at least one real or sandbox webhook through the current local stack. Last modified on March 30, 2026