Securing Paddle Webhooks with Signature Verification
When a payment is processed, Paddle sends a webhook payload to your backend. Because these webhooks trigger database upgrades, you must verify that the incoming HTTP request is genuine and was sent by Paddle.
1. Webhook Signature Verification Flow
Paddle appends a signature string to the Paddle-Signature header of every HTTP POST request. The header contains:
- ts: Timestamp representing when the signature was created.
- h1: SHA256 cryptographic hash calculated using the raw body payload and your Webhook Secret Key.
2. Implementing the Next.js API Verifier
Install the official Paddle Node.js SDK to handle signature parsing:
# Install the Paddle backend SDK
npm install @paddle/paddle-node-sdkCreate an API route endpoint that verifies the signature before editing data:
// app/api/webhooks/paddle/route.ts
import { NextResponse } from "next/server";
import { Paddle } from "@paddle/paddle-node-sdk";
const paddle = new Paddle({
apiKey: process.env.PADDLE_API_SECRET_KEY as string,
environment: "sandbox",
});
export async function POST(request: Request) {
const signature = request.headers.get("paddle-signature");
const rawRequestBody = await request.text();
if (!signature) {
return new Response("Missing signature header", { status: 400 });
}
// 1. Verify cryptographic authenticity
try {
const webhookSecret = process.env.PADDLE_WEBHOOK_SECRET_KEY as string;
const isValid = paddle.webhooks.isValidSignature(rawRequestBody, webhookSecret, signature);
if (!isValid) {
console.warn("Signature verification failed.");
return new Response("Invalid signature", { status: 401 });
}
} catch (err: any) {
console.error("Verification error:", err.message);
return new Response("Verification failed", { status: 400 });
}
// 2. Parse payload event
const event = JSON.parse(rawRequestBody);
console.log("Successfully verified event:", event.event_type);
return NextResponse.json({ received: true });
}3. Registering the Webhook URL in Paddle
- In the Sandbox Dashboard, navigate to Developer Settings -> Webhooks.
- Click Create Webhook.
- Enter your destination URL (for example,
https://mycompany.com/api/webhooks/paddle). - Select the events you want to monitor (for example,
transaction.completed,subscription.created,subscription.canceled). - Save. Copy the webhook secret key and add it to your local environment file.
Published on Last updated: