Skip to main content

Why verify

Your webhook endpoint is a public URL, so anyone could POST to it. Every StockInsights delivery is signed with a secret only you and StockInsights know. Verifying the signature on each request proves it genuinely came from StockInsights and that the body was not altered in transit.
Verify the signature before you trust or act on any webhook payload.

Request headers

Each delivery includes these headers:

How the signature works

The X-StockInsights-Signature header has two comma-separated fields:
  • t — the UNIX timestamp (seconds) when the signature was generated.
  • v1 — a hex-encoded HMAC-SHA256 of the string {t}.{raw_body}, keyed by your signing secret.
The signed string is the timestamp, a literal ., then the exact raw request body. To verify, recompute the HMAC and compare it to v1 in constant time.
Your signing secret is hex-encoded. Decode it to raw bytes before using it as the HMAC key. Compute the HMAC over the raw request body exactly as received — do not parse and re-serialize the JSON first, or the bytes (and the signature) will differ.

Verify a signature

Using it in a handler

Timestamp tolerance and replay

The timestamp in t lets you reject old requests. StockInsights signs with the current time, and the examples above reject anything more than 300 seconds (5 minutes) from your server’s clock. This limits how long a captured request could be replayed against your endpoint. Keep your server clock in sync (NTP) so legitimate requests are not rejected for clock drift. If your endpoint sits behind a proxy that buffers requests, make sure the tolerance comfortably exceeds any added delay.

Rotating the secret

Rotating the signing secret (from Account Settings → Webhooks) issues a new secret and invalidates the previous one immediately. There is no overlap window in which both secrets verify, so plan the swap:
  1. Rotate in the dashboard and copy the new secret.
  2. Deploy it to your endpoint promptly.
Between those two steps, deliveries are signed with the new secret while your endpoint still holds the old one, so they will fail verification.
What happens to those deliveries depends entirely on the status code your handler returns. A 5xx (as in the examples above) is retried, so the events land once the new secret is deployed. A 4xx is treated as a permanent failure and those events are dropped. If your handler returns 400 or 401 on an invalid signature, change it to a 5xx before you rotate.
Rotation is only needed if the secret may have been exposed. You do not need to rotate to recover a secret you did not save — it can be revealed again at any time from the destination card in the dashboard.