For developers

Standard Webhooks payload signer

Type an id, a timestamp and a raw body, give a whsec_ secret, and get the exact webhook-id, webhook-timestamp and webhook-signature headers for it.

Free, no accountIn your browser

The id this delivery carries. Any value works for a local test; a real one is always evt_... .

Plain Unix seconds, the same units a real delivery carries - not milliseconds, not an ISO string.

The exact bytes your test receiver will get - whatever is typed here is signed as-is.

Starts with "whsec_" - one made by the signing secret generator, or the real one from the dashboard.

Try

Result

Headers generated

The three headers a delivery carrying this id, timestamp and body would have, signed with the secret you gave - paste them into a local request to test a receiver end to end.

Headers

webhook-id: evt_01JABCDEFG1234567890ABCD webhook-timestamp: 1760000000 webhook-signature: v1,Rr7mGQ5OHmZmbqDv1127q/hj/T4p6hOIcTwuPIwCbGU=

webhook-signature follows the Standard Webhooks specification: HMAC-SHA256 over "id.timestamp.body", base64-encoded, prefixed "v1,".

  • This signs exactly what you typed - it makes no request of its own and cannot confirm your receiver actually accepts these headers.

What this is

This standard webhooks payload signer computes the three headers a real delivery carries - webhook-id, webhook-timestamp and webhook-signature - from whatever id, timestamp, body and whsec_ secret you give it, so a local receiver can be sent a correctly signed test request before a live endpoint exists.

Our signing follows the Standard Webhooks specification, not a scheme invented for ResellerHQ alone: `packages/events/src/signing.ts`'s `signWebhook` computes an HMAC-SHA256 over the exact bytes `id.timestamp.body`, base64-encodes the result, and prefixes it `v1,` before it ships as the `webhook-signature` header next to `webhook-id` and `webhook-timestamp`. This page runs the same construction in the browser so the three headers it hands back are exactly what a real delivery carrying this id, timestamp and body would have.

How to read the result

The "Headers" block below is the whole result: three lines, ready to paste as headers on a request to your own local receiver, or alongside the raw body in whatever is sending the test request. Changing a single character in the id, the timestamp, the body or the secret changes the whole webhook-signature value, so a receiver that expects an exact match will reject anything reformatted along the way.

"Verifying one of our webhooks" uses this same signing construction as the worked example it recomputes by hand in bash, Python and Node, then covers what this page does not: our retry schedule, turning a documented operation into a ready request, and every error code our API can answer with.

Common mistakes

What goes wrong most often, and how to tell.

  • Reformatting the body before sending itThe signature is computed over the exact bytes typed into the body field above - a receiver that re-indents, re-parses or otherwise changes the body before checking the signature against it will see a mismatch, even though nothing about the content actually changed.
  • Expecting a secret made here to verify a real deliveryThese headers only prove the arithmetic holds for the secret you typed in - they say nothing about a secret ResellerHQ itself would ever sign a real delivery with. Use the signing secret generator for a throwaway whsec_ value, or the real one shown once in the dashboard, not a guess.

Questions

What people ask about this tool.

  • Yes, for the exact id, timestamp, body and secret given - `signWebhook` in `packages/events/src/signing.ts` computes the webhook-signature header the same way, following the Standard Webhooks specification, so a receiver built to verify a real delivery can be tested against what this page produces without any special-casing.
  • No - ResellerHQ itself sends the real delivery, with its own id and timestamp, signed with the secret shown once when the endpoint was created. This page is for testing a receiver locally, with values and a secret you control, before or alongside a real endpoint.
  • Because that is the exact unit `webhook-timestamp` carries on a real delivery - a plain whole number of seconds since the Unix epoch, never milliseconds and never an ISO string - so a header built here matches the shape a receiver's own parsing code expects.
  • The signing secret generator makes a whsec_-shaped secret for exactly this kind of local testing, with no real delivery behind it; a live endpoint's own real secret is shown once in the dashboard under Developers, at the moment the endpoint is created.

Sources

Every fixed value here comes from the provider’s own documentation. These pages change, so each says the day it was last read.

Use it from the API

The same check, as one request.

Request
curl -X POST https://resellerhq.com/api/tools/standard-webhooks-payload-signer \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "tool": "standard-webhooks-payload-signer",
  "input": {
    "webhookId": "evt_01JABCDEFG1234567890ABCD",
    "webhookTimestamp": "1760000000",
    "body": "{\"type\":\"number.message.received\",\"data\":{\"number\":\"15550100002\"}}",
    "secret": "whsec_GBAa/MjfYOnqrI7OlnVtVh2XZeKLGILY"
  },
  "result": {
    "verdict": {
      "tone": "neutral",
      "headline": "Headers generated",
      "summary": "The three headers a delivery carrying this id, timestamp and body would have, signed with the secret you gave - paste them into a local request to test a receiver end to end."
    },
    "findings": [],
    "parts": [
      {
        "kind": "record",
        "title": "Headers",
        "value": "webhook-id: evt_01JABCDEFG1234567890ABCD\nwebhook-timestamp: 1760000000\nwebhook-signature: v1,Rr7mGQ5OHmZmbqDv1127q/hj/T4p6hOIcTwuPIwCbGU=",
        "note": "webhook-signature follows the Standard Webhooks specification: HMAC-SHA256 over \"id.timestamp.body\", base64-encoded, prefixed \"v1,\".",
        "copyLabel": "Copy headers"
      }
    ],
    "limits": [
      "This signs exactly what you typed - it makes no request of its own and cannot confirm your receiver actually accepts these headers."
    ]
  }
}

Build on the same API this tool is part of: numbers, domains and mailboxes, one key.

Read the API

Company names and logos are trademarks of their owners, shown only to identify each service.