Surge

Signature Verification

Surge signs every outbound webhook request following the Standard Webhooks specification. Verifying the signature confirms that the request came from Surge and wasn't tampered with in transit.

The three headers

Surge sets these headers on every webhook POST:

HeaderDescription
webhook-idUnique ID for this webhook delivery attempt
webhook-timestampUnix timestamp (seconds) when the event was sent
webhook-signatureHMAC-SHA256 signatures, comma-separated, each prefixed with v1,

The webhook-signature header may contain multiple v1,<signature> values separated by spaces if your platform has multiple signing secrets (during key rotation). Accept the request if any signature verifies successfully.

Signing algorithm

Surge computes the signature as:

HMAC-SHA256(secret, "{webhook-id}.{webhook-timestamp}.{raw-body}")

The secret is base64-encoded and prefixed with whsec_ in the dashboard. Strip the prefix and base64-decode it before using it as the HMAC key.

The signed message is the string webhook-id, a literal ., webhook-timestamp, a literal ., and then the raw request body, all concatenated without any separating whitespace beyond the . characters.

Replay protection

The webhook-timestamp lets you reject replays. Surge recommends rejecting requests where webhook-timestamp is more than five minutes old. Most Standard Webhooks library implementations enforce this tolerance window automatically.

Verification examples

from standardwebhooks import Webhook
import os

wh = Webhook(os.environ["SURGE_WEBHOOK_SECRET"])

try:
    payload = wh.verify(request.body, request.headers)
    # payload is the parsed event dict
except Exception:
    return Response(status=400)

Finding your webhook secret

Your signing secret is shown in the dashboard at Settings → Webhooks, next to each endpoint URL. It looks like whsec_<base64-encoded-bytes>.

Deprecated header

Important

Earlier Surge versions used surge-signature instead of webhook-signature. If you are still reading surge-signature, migrate to webhook-signature. See Deprecation Notices.