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 suite

Reference 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 });
}