Webhooks
MantleWP receives webhooks from Stripe to handle subscription changes, payment failures, and billing events. This page explains how webhook processing works and which events are handled.
Stripe Webhooks
MantleWP receives Stripe webhooks at POST /api/webhooks/stripe. Stripe signs each webhook request with a secret, so MantleWP can verify that the request actually came from Stripe and wasn't tampered with.
Handled Events
MantleWP handles the following Stripe webhook events:
| Event | Action |
|---|---|
| checkout.session.completed | Activate subscription, update organization plan tier |
| customer.subscription.updated | Sync plan changes (upgrade, downgrade, billing cycle) |
| customer.subscription.deleted | Mark subscription as canceled, enforce free plan limits |
| invoice.payment_succeeded | Record successful payment, update billing status |
| invoice.payment_failed | Mark organization as past due, send notification to owner |
Webhook Security
Every incoming webhook is verified against the Stripe webhook signing secret (STRIPE_WEBHOOK_SECRET). Requests that fail signature verification return 400 Bad Request and are not processed.
The raw HTTP request body is used for verification — the body must never be parsed before verification completes.
// Verify webhook signature
const sig = request.headers.get('stripe-signature');
const event = stripe.webhooks.constructEvent(
rawBody,
sig,
STRIPE_WEBHOOK_SECRET
);
// Process event only after successful verificationRetry Behavior
Stripe automatically retries failed webhook deliveries for up to 3 days. If your server returns an error status (5xx), Stripe will retry the webhook later.
Webhook events are idempotent — processing the same event twice (due to a retry) should have no side effect. MantleWP tracks processed event IDs to prevent duplicate processing.
Testing Webhooks Locally
Use the Stripe CLI to simulate webhook events during local development:
# Install Stripe CLI
brew install stripe/stripe-cli/stripe
# Forward Stripe events to your local server
stripe listen --forward-to localhost:3000/api/webhooks/stripe
# Trigger a test event in another terminal
stripe trigger customer.subscription.updatedThe Stripe CLI displays all webhook events sent to your endpoint, making it easy to test billing flows locally.
Example Webhook Event
Here's what a checkout.session.completed webhook looks like:
{
"id": "evt_1234567890",
"object": "event",
"api_version": "2023-10-16",
"created": 1234567890,
"type": "checkout.session.completed",
"data": {
"object": {
"id": "cs_live_abc123xyz",
"customer": "cus_abc123",
"subscription": "sub_abc123",
"client_reference_id": "org_12345"
}
}
}Next steps: Back to API Reference, read about billing and plans, or check authentication.