Webhooks
Latch uses Stripe webhooks to keep subscription state in sync.
Endpoint
Section titled “Endpoint”POST /api/v1/webhooks/stripeThis route uses Stripe signature verification instead of API keys.
Supported events
Section titled “Supported events”| Stripe event | Latch behavior |
|---|---|
checkout.session.completed | Creates or updates a subscription for the existing customerId stored in checkout metadata |
customer.subscription.created | Stores a new Stripe-backed subscription |
customer.subscription.updated | Updates subscription state and billing period |
customer.subscription.deleted | Marks a subscription cancelled |
invoice.payment_failed | Marks a subscription past_due |
invoice.payment_succeeded | Marks a subscription active |
customer.created | Updates stored Stripe customer metadata |
customer.updated | Updates stored Stripe customer metadata |
Production
Section titled “Production”When you save your Stripe secret key in Settings > Stripe, Latch automatically creates a webhook endpoint in your Stripe account with the correct URL and events. No manual configuration needed.
Local development
Section titled “Local development”Stripe can’t reach localhost, so automatic webhook creation is skipped. Use the Stripe CLI instead:
stripe listen --forward-to http://localhost:4000/api/v1/webhooks/stripeThen either:
- Set
STRIPE_WEBHOOK_SECRET=whsec_...in your environment, or - Pass the signing secret when saving Stripe settings in the dashboard
Manual setup
Section titled “Manual setup”If you prefer to create the webhook endpoint yourself in the Stripe Dashboard, select the events listed above and point the URL to https://your-api-domain/api/v1/webhooks/stripe. Pass the signing secret as webhookSecret when saving Stripe settings — Latch will skip automatic creation when a manual secret is provided.
Signature verification
Section titled “Signature verification”Latch validates webhook signatures with the configured Stripe webhook secret.
It can use:
- the environment-level webhook secret (
STRIPE_WEBHOOK_SECRET) - the per-publication stored webhook secret (auto-created or manual)
Requests with missing or invalid signatures are rejected.
Idempotency and retries
Section titled “Idempotency and retries”When Stripe is available, webhook events are queued and retried asynchronously. If queueing is unavailable, the route falls back to synchronous handling.
Subscription status mapping
Section titled “Subscription status mapping”| Stripe status | Latch status |
|---|---|
active | active |
trialing | trialing |
past_due | past_due |
canceled | cancelled |
unpaid | past_due |