Processing Subscription Lifecycle Events
Once a webhook signature is verified, parse the event payload and update your local database to manage user premium access.
1. Essential Webhook Event Types
To handle subscriptions, monitor these event notifications:
subscription.created: Sent when a user completes their initial subscription payment.subscription.updated: Sent when a plan is upgraded, downgraded, or a payment cycle renews.subscription.canceled: Sent when the subscription is cancelled and premium access is terminated.
2. Implementing the Event Handler Action
Update your API webhook route to parse the events and write data using Prisma:
// app/api/webhooks/paddle/route.ts (Continued)
import { prisma } from "../../../lib/prisma";
export async function processVerifiedEvent(event: any) {
const eventType = event.event_type;
const data = event.data;
switch (eventType) {
case "subscription.created": {
const customerId = data.customerId;
const subscriptionId = data.id;
const priceId = data.items[0].priceId;
// Look up custom client details attached to the transaction
const userId = data.customData?.userId;
if (userId) {
// Link subscription to user account and upgrade status
await prisma.user.update({
where: { id: userId },
data: {
paddleCustomerId: customerId,
paddleSubscriptionId: subscriptionId,
pricingTier: "pro", // Set role tier
subscriptionActive: true,
},
});
}
break;
}
case "subscription.updated": {
const subscriptionId = data.id;
const status = data.status; // Options: active, trialing, past_due, paused
const isSessionActive = status === "active" || status === "trialing";
await prisma.user.updateMany({
where: { paddleSubscriptionId: subscriptionId },
data: {
subscriptionActive: isSessionActive,
},
});
break;
}
case "subscription.canceled": {
const subscriptionId = data.id;
// Revoke user premium access
await prisma.user.updateMany({
where: { paddleSubscriptionId: subscriptionId },
data: {
pricingTier: "free",
subscriptionActive: false,
},
});
break;
}
default:
console.log(`Unhandled Paddle event category: ${eventType}`);
}
}3. Important Design Advice
- Idempotency: Webhook events can occasionally be delivered twice. Ensure your database operations update records using unique keys (such as
paddleSubscriptionId) to avoid duplicate row creation. - Metadata Pass-Through: When opening checkout windows in the client, always attach
userIdinside thecustomDatapayload. This guarantees you can associate webhook payloads back to specific accounts.
Published on Last updated: