Verifying Deepwick webhook signatures — Node, Python, and Go
Every Deepwick alert ships an HMAC-SHA256 signature in X-Deepwick-Signature. Here are drop-in verifiers for the three stacks we see most often — and the two failure modes that catch teams out in production.
If you set a webhook URL when you created a Deepwick alert, we POST to it every time the alert fires. We sign every payload with an HMAC-SHA256 keyed on the per-alert secret we returned once at creation time. The signature goes in the header in the format .
Verifying it on your side is five lines of code. Skipping it is a common way to end up with someone else's script calling your endpoint and triggering real trades.
What we send
Every alert fire delivers a POST to your URL with these headers:
- - -
- — stable per delivery, useful for idempotency
- -
- — HMAC-SHA256 over the raw request body
- — only present on manual retries from the dashboard
The body is a JSON object:
The two failure modes that catch teams out
1. Comparing signatures in a non-constant-time way. The classic check on signature strings leaks information through timing differences. Use a constant-time comparator (every language has one — Node's , Python's , Go's ).
2. Re-serializing the JSON before verifying. If you and then before HMACing, the key order changes, whitespace changes, and the signature breaks. Always HMAC the raw bytes that came off the wire. Deepwick signs the exact body we send.
Node.js (Express, Fastify, plain http, etc.)
verify: (req, res, buf) // => { req.rawBody = buf }
Python (Flask, FastAPI, Django, etc.)
Go (net/http, chi, gin, echo)
Rotating the secret
If a secret leaks (an ex-employee, a leaked log, a commit history), rotate it without losing the alert:
The endpoint returns the new plaintext secret once. Update your verifier with it. There is no overlap window — Deepwick signs with the new secret immediately. Plan the cutover so your verifier accepts the old OR new secret during the deploy.
Idempotency
is stable across retries. Store it. If you see the same ID twice (network glitch + a manual retry from the dashboard), treat the second delivery as a no-op. We don't currently have at-least-once delivery guarantees, but the event ID is your hook for building them.
The cron retries for you
The cron does a single retry on 5xx or network errors. After that the event row is marked in and you can re-deliver from the dashboard with one click. The retry re-signs the same body and re-POSTs to the same URL. Your verifier sees the same — that's your signal to dedupe.
That's it. Five lines per stack, two failure modes to avoid, and you have a webhook that's safe to drive real trades from.