Verify Square Webhook Signatures
Square signs each webhook with HMAC-SHA256 over your notification URL concatenated with the raw request body and sends the base64 result in the x-square-hmacsha256-signature header. The key is the signature key of that webhook subscription. Enter the notification URL exactly as configured, the raw body, the key and the header value.
Everything runs in your browser — the payload and secret never leave this page. Want to verify a different provider? See the webhook signature verifier hub or the generic HMAC generator.
How Square signs webhooks
- Take the full notification URL exactly as configured in your subscription — scheme, host, path and any trailing slash must match.
- Concatenate that URL directly with the raw request body: URL first, body second, with no separator.
- Compute HMAC-SHA256 of the combined string using your subscription's signature key as the key.
- Base64-encode the digest and constant-time compare it to
x-square-hmacsha256-signature.
Verify Square signatures in code
const crypto = require('crypto');
// notificationUrl must match the subscription URL exactly (incl. trailing slash).
const expected = crypto
.createHmac('sha256', process.env.SQUARE_SIGNATURE_KEY)
.update(notificationUrl + rawBody) // URL first, then the raw body
.digest('base64');
const received = req.headers['x-square-hmacsha256-signature'];
const valid = crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(received));import hmac, hashlib, base64
payload = notification_url.encode() + raw_body # URL + raw body, no separator
expected = base64.b64encode(hmac.new(
signature_key.encode(), payload, hashlib.sha256).digest()).decode()
received = request.headers['x-square-hmacsha256-signature']
valid = hmac.compare_digest(expected, received)Frequently asked questions
Which key signs Square webhooks?
The signature key for that specific webhook subscription, shown in the Square Developer Dashboard under Webhooks → Subscriptions. Each subscription has its own key, and it is used as a raw string — not base64-decoded.
Why does my Square signature never match?
The most common cause is the notification URL not matching exactly: a missing or extra trailing slash, http vs https, or a proxy rewriting the host all change the result. Sign with the URL you configured in the subscription, and use the raw request body.
Does Square sign a timestamp?
No. The modern HMAC-SHA256 scheme signs only the URL plus body, so there is no built-in replay protection — rely on HTTPS and idempotent handling. The legacy x-square-signature header (HMAC-SHA1) is deprecated; verify x-square-hmacsha256-signature instead.
Verify other providers
Receiving Square webhooks on a server behind a firewall or on localhost? Webhook Relay can forward them to your internal service and even verify or transform them before delivery.
