API
GuidesGet API token
Webhooks

Webhook validation

Webhooks created through the API are signed using your API Client Secret so you can verify that each request came from Recharge. Every webhook delivery includes two signature schemes: a recommended timestamp-bound scheme that we encourage for all new integrations, and a legacy body-only scheme that remains supported.

The API Client Secret is not the same as your API token. You can find it at:
Recharge Dashboard → Integrations → API Tokens → Click on your token
The Edit API Token page will show your API Client Secret.

Recommended: timestamp-bound signature

Each webhook request includes two headers:

Header Value
X-Recharge-Webhook-Timestamp Unix epoch seconds (integer) at the time the request was signed.
X-Recharge-Webhook-Signature Comma-separated key/value pairs in the form t=<epoch>,v1=<hex>. Future schemes may add v2=….

To verify a delivery:

  1. Read the timestamp t from X-Recharge-Webhook-Signature (it matches the value in X-Recharge-Webhook-Timestamp).
  2. Construct the signing input by concatenating the timestamp, a literal ., and the exact JSON payload bytes as transmitted: "<timestamp>.<payload_json>". The payload must be the unmodified raw body — re-serializing JSON will change whitespace and break verification.
  3. Compute HMAC-SHA-256 over the signing input, keyed by your API Client Secret. Compare the hex digest to the v1 value from X-Recharge-Webhook-Signature using a constant-time comparison.
  4. Reject the delivery if abs(now - t) > 172800 seconds (48 hours) to protect against replay attacks.

Preserve header casing verbatim: X-Recharge-Webhook-Timestamp and X-Recharge-Webhook-Signature.

Legacy: X-Recharge-Hmac-Sha256

For backward compatibility, every webhook also includes the legacy X-Recharge-Hmac-Sha256 header. Existing integrations using this header continue to work and do not need to change immediately, but new integrations should use the timestamp-bound scheme above.

The legacy header is computed by concatenating the API Client Secret with the JSON-stringified request body and hashing the result with SHA-256. The body must be the exact JSON string as transmitted — even a lost or added space will cause validation to fail.

Related guides: Example code for validating webhooks