Auto-Handled
Core events handled by platform
Forwarding
Forward to your app for custom logic
Verified
Cryptographic signature validation
Auto-Retry
Exponential backoff on failures
Platform-Handled Events
These Stripe events are automatically handled by the platform - no setup required:
checkout.session.completedCreates subscription record
customer.subscription.createdActivates subscription
customer.subscription.updatedUpdates plan/status
customer.subscription.deletedMarks subscription ended
invoice.payment_succeededRecords successful payment
invoice.payment_failedUpdates status to past_due
No Setup Required
App Webhook Forwarding
Configure in Dashboard
Go to App Settings → Billing → Webhooks and add your endpoint URL.
Select Events
Choose which events to forward to your app.
Copy Signing Secret
Copy the webhook signing secret to verify incoming webhooks.
import { platform } from '@/lib/platform'
import { NextRequest } from 'next/server'
export async function POST(req: NextRequest) {
const body = await req.text()
const signature = req.headers.get('stripe-signature')!
// Verify and parse the webhook
const event = await platform.billing.verifyWebhook({
body,
signature,
secret: process.env.SYLPHX_WEBHOOK_SECRET!,
})
switch (event.type) {
case 'subscription.created':
await sendWelcomeEmail(event.data.userId, event.data.plan)
break
case 'subscription.canceled':
await sendCancellationSurvey(event.data.userId)
break
case 'payment.failed':
await sendPaymentFailedEmail(event.data.userId)
break
case 'subscription.upgraded':
await unlockFeatures(event.data.userId, event.data.newPlan)
break
}
return new Response('OK', { status: 200 })
}Webhook Events
Available webhook events for forwarding:
subscription.createdNew subscription startedsubscription.upgradedUser upgraded to higher plansubscription.downgradedUser downgraded to lower plansubscription.canceledUser canceled subscriptionsubscription.renewedSubscription renewed for new periodsubscription.expiredSubscription endedtrial.startedFree trial begantrial.endingTrial ends in 3 daystrial.endedTrial converted or expiredpayment.succeededPayment processed successfullypayment.failedPayment failedEvent Payload
Webhook event structure:
| Property | Type | Description |
|---|---|---|
id | string | Unique event ID |
type | string | Event type (e.g., subscription.created) |
createdAt | Date | When the event occurred |
data.userId | string | User ID |
data.subscriptionId | string | Subscription ID |
data.plan | object | Current plan (id, slug, name) |
data.previousPlan | object? | Previous plan (for upgrades/downgrades) |
data.status | string | Subscription status |
Testing Webhooks
Test webhooks locally using the Stripe CLI:
# Install Stripe CLI
brew install stripe/stripe-cli/stripe
# Login
stripe login
# Forward webhooks to your local server
stripe listen --forward-to localhost:3000/api/webhooks/billing
# Trigger test events
stripe trigger checkout.session.completedDashboard Testing
Retry Policy
If your webhook endpoint returns a non-2xx status code, the platform retries with exponential backoff:
After 5 failed attempts, the webhook is marked as failed. You can view failed webhooks and manually retry them in the dashboard.