Cosmovex Tools

Square webhook signature invalid? Capture the event and check the URL-plus-body HMAC

Square with Hookwatch Webhook Tester

This inbox is set up as a Square webhook notification URL. Subscribe to events in the Developer Console, trigger one in Sandbox, and the delivery appears here with its event_id, type and payload. The Signature tab is already configured for Square: HMAC-SHA256 of the notification URL followed by the raw body, base64, so you only paste the subscription's signature key.

  1. Copy the inbox URL. It ends in /square, and every character of it, including the path, is part of what Square signs.
  2. In the Square Developer Console open your app → Webhooks → Subscriptions, switch to Sandbox, add a subscription with this notification URL and the events you handle.
  3. Trigger an event: create a payment or a customer with API Explorer in Sandbox, or press Send a signed test Square event here first.
  4. Select the request. The Signature tab is set to x-square-hmacsha256-signature with the template {url}{body}, where {url} is this inbox URL plus the path the request used.
  5. Paste the signature key. Valid means the key and URL are right; your server must sign the same URL string, not the internal URL it sees behind a proxy.
square webhook signature square webhook signature keysquare webhook testerx-square-hmacsha256-signaturesquare webhook eventssquare payment webhook
Open Hookwatch Webhook Tester Free · Pro $5/mo · no account

What to know

Square signs a delivery with HMAC-SHA256 over the notification URL of the subscription followed directly by the raw request body, keyed with the subscription's signature key, and sends the digest base64-encoded in x-square-hmacsha256-signature. Because the URL is part of the signed string, the most common failure is the same one Twilio users hit: the server validates with the URL it sees after a proxy or load balancer, with http instead of https, another host or a trailing slash, rather than the URL saved in the subscription. The SDK helper WebhooksHelper.isValidWebhookEventSignature takes that URL as an argument for this reason.

Sandbox and production subscriptions are configured separately and each has its own signature key, so a key copied from the Sandbox subscription never verifies a production event. Updating the notification URL of a subscription changes what is signed. If you test here and then point the subscription at your server, the signed URL changes with it; the {url} part of the template on this page always uses this inbox's URL.

Square retries a notification that does not get a 2xx response within 10 seconds, with exponential backoff for up to 24 hours, and adds square-retry-number and square-retry-reason headers to retries. Webhooks can also be sent more than once without a failure, and ordering is not guaranteed. Use event_id in the body as an idempotency key, and for payment.updated read the payment's current status rather than assuming events arrive in sequence.

An event body has merchant_id, type (payment.updated, order.created, customer.created…), event_id, created_at and data with type, id and object, where object holds the changed resource. Amounts are integers in the smallest currency unit inside amount_money, so 2500 with currency USD is $25.00. The Compare view (Pro) helps with payment.updated, which fires several times per payment as it moves from APPROVED to COMPLETED.

Updated · Cosmovex

Questions

What does Square sign in a webhook?

The subscription's notification URL followed directly by the raw body, with HMAC-SHA256 and the signature key, base64-encoded in x-square-hmacsha256-signature. Show the exact signed string in the Signature tab displays that URL-plus-body for any request.

Why is my Square webhook signature invalid with the right key?

The URL your server passes to the check differs from the notification URL in the subscription: scheme, host, port, path or trailing slash. Hard-code the public notification URL in the verification call instead of rebuilding it from the incoming request.

Where do I find the Square webhook signature key?

In the Developer Console open your app → Webhooks → Subscriptions and select the subscription. Sandbox and production subscriptions have different keys.

How do I trigger a Square test event?

Subscribe in Sandbox, then call an API that changes something, for example CreatePayment or CreateCustomer in API Explorer against your Sandbox account. The resulting payment or customer event is delivered and signed like a production one.

Does Square send duplicate webhooks?

It can. Retries happen when no 2xx arrives within 10 seconds, and duplicates are possible otherwise too. Store event_id and skip events you have already processed.

The free plan covers everything on this page. Hookwatch Webhook Tester Pro ($5/mo, billed monthly) is described on the Hookwatch Webhook Tester page.