Provider standard
Shopify webhook signature verification
Shopify signs every delivery. Your receiver must verify x-shopify-hmac-sha256 against the raw request body before processing anything. Official documentation.
Test your Shopify receiver now
The free verification suite dispatches all eight vectors — valid signature, tampered body, corrupted signature, expired and future timestamps, missing header, rapid replay, and malformed JSON — against your endpoint in seconds.
Run the verification suiteReference implementations
Correct verification code for Shopify webhooks, per framework.
Next.js App Router Generic HMAC Verification
import { NextRequest, NextResponse } from "next/server";
import crypto from "node:crypto";
export async function POST(req: NextRequest) {
const signature = req.headers.get("x-signature-sha256");
const timestamp = req.headers.get("x-timestamp");
if (!signature || !timestamp) {
return NextResponse.json({ error: "Missing authentication headers" }, { status: 400 });
}
// Check timestamp drift (5 min tolerance)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
return NextResponse.json({ error: "Timestamp out of range" }, { status: 400 });
}
const rawBody = await req.text();
const toSign = `${timestamp}.${rawBody}`;
const expectedSig = crypto
.createHmac("sha256", process.env.WEBHOOK_SIGNING_SECRET!)
.update(toSign)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig))) {
return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
}
return NextResponse.json({ success: true });
}