Stripe Webhooks API
Signature verification, idempotency, and payment status updates.
Endpoint
POST /api/webhooks/stripe
Processing requirements
Critical requirement
Read raw body text before constructing event.
const body = await req.text();
const sig = headers().get("stripe-signature");
const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
If body is parsed as JSON first, signature verification fails.
Primary event focus
checkout.session.completed
Typical state transition
- Locate target payment record
- Mark
statustoSUCCEEDED - Persist
stripePaymentIntentId - Set
paidAttimestamp
Required behavior
Before applying update logic, check if the payment intent was already recorded.
Rationale
Webhook retries are normal. Handlers must be safe to execute more than once.
Failure handling
- Invalid signature: reject request (
400) - Unknown event types: safely ignore or log for observability
- Processing errors: return retry-safe status and preserve traceability in logs