Webhooks tell your app when an email is delivered, bounces or is received. Anyone can post to a public URL, so verify every request before you act on it. Use the @sendpanda/webhooks package; it needs Node.js 22 or newer.
1. Install
npm install @sendpanda/webhooksVerification uses the endpoint's webhook signing secret, not your API key. Store it as SENDPANDA_WEBHOOK_SECRET.
2. Verify the raw body in a Next.js route handler
// app/api/webhooks/sendpanda/route.ts
import { verifyWebhook, WebhookVerificationError } from "@sendpanda/webhooks";
export const runtime = "nodejs";
export async function POST(request: Request) {
const rawBody = await request.text(); // before any JSON parsing
let event;
try {
event = verifyWebhook(
rawBody,
request.headers,
process.env.SENDPANDA_WEBHOOK_SECRET!,
);
} catch (error) {
if (error instanceof WebhookVerificationError)
return new Response("Invalid webhook", { status: 400 });
throw error;
}
await persistReceiptAndQueue(event); // your own durable storage
return new Response(null, { status: 204 });
}The signature covers the exact bytes SendPanda sent. A parsed object or re-serialised JSON will not match. In Express, mount express.raw({ type: "application/json" }) on the webhook route before express.json() and pass request.body and request.headers.
3. Deduplicate by event ID
Verification proves the event is authentic. It does not make your side effects idempotent. Deliveries can be retried or replayed with the same event.id and a fresh timestamp and signature, so store the ID durably and skip events you have already handled. Acknowledge only after the event is safely recorded.
Rotating signing secrets
During rotation, deliveries carry signatures for both secrets for 24 hours. Pass both and the helper accepts either:
const event = verifyWebhook(rawBody, request.headers, [
currentSecret,
previousSecret,
]);The default timestamp tolerance is 300 seconds in either direction, so keep your server clock synchronised. Never log the signing secret or message content.
Next steps
- Quickstart for the full first-send walkthrough.
- Verify webhooks to learn when an email is delivered or bounces.
- Pricing: 1,000 emails a month free, no card.