Square sends an x-square-hmacsha256-signature header. It's an HMAC-SHA256 built from three things: your subscription's signature key, the subscription's notification URL, and the raw request body. The signed string is the URL followed directly by the body, and the result is base64-encoded. Unlike most providers, Square includes the URL, and that's where most failures come from.
http://, an internal host or a different path. A trailing-slash difference also breaks it. Hard-code the configured URL or load it from config.x-square-signature (HMAC-SHA1). Verify x-square-hmacsha256-signature instead.import { WebhooksHelper } from 'square';
app.post('/square', express.raw({ type: 'application/json' }), async (req, res) => {
const ok = await WebhooksHelper.verifySignature({
requestBody: req.body.toString('utf8'),
signatureHeader: req.get('x-square-hmacsha256-signature') || '',
signatureKey: process.env.SQUARE_SIGNATURE_KEY,
notificationUrl: process.env.SQUARE_NOTIFICATION_URL, // exactly as configured
});
if (!ok) return res.sendStatus(403);
res.sendStatus(200); // then process; de-dupe on event_id
});
expected = base64.b64encode(hmac.new(key.encode(), (NOTIFICATION_URL + raw_body).encode(), hashlib.sha256).digest()).decode()
ok = hmac.compare_digest(expected, request.headers.get('x-square-hmacsha256-signature', ''))
The guide is Stripe-only. The kit is a self-hosted Cloudflare Worker relay that adds retries, replay and a dead-letter list in front of your endpoint. It verifies Square's x-square-hmacsha256-signature out of the box. Set SCHEME_<ID>=square and your notification URL. It works the same way for Stripe, Lemon Squeezy, Shopify, Paddle Billing, Twilio (status callbacks) and GitHub.
Fix Your Stripe Webhooks guide · Self-Hosted Webhook Relay Kit. Code LAUNCH40 = 40% off until Sun Oct 11, 6:40 AM MT.
Square's docs say the notification URL must use HTTPS and must respond with a 2xx as soon as possible. Notifications can arrive more than once, so de-duplicate on the event_id in the body.
Free download: Webhook debugging cheat sheet.
Fighting webhooks on more than one platform? The Fix Your Stripe Webhooks guide ($9) covers raw-body and signature problems in depth, and the Self-Hosted Webhook Relay Kit ($19) adds retries, replay and a dead-letter list in front of any endpoint.