webhooks
Signer les requêtes
Comment signer vos POSTs webhook en HMAC-SHA256 pour que Spectra les vérifie.
Chaque POST sur un webhook Spectra doit porter une signature HMAC-SHA256 du corps. Les requêtes non signées ou à signature invalide sont rejetées avec 401 Unauthorized.
La signature
X-Spectra-Signature: sha256=<hex>
X-Spectra-Timestamp: <unix-ms>
La signature est calculée sur <timestamp>.<body> (séparé par un
point) :
import hmac, hashlib, time
secret = b"<vos bytes de secret>"
ts = str(int(time.time() * 1000))
body = '{"action":"buy","symbol":"BTCUSDT","qty":1}'
mac = hmac.new(secret, f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
headers = {
"X-Spectra-Signature": f"sha256={mac}",
"X-Spectra-Timestamp": ts,
"Content-Type": "application/json",
}
Pourquoi le timestamp
Inclure le timestamp dans le payload signé lie le message à un instant. Un message capturé et rejoué après la fenêtre de 5 minutes échoue à la vérification — voir Replay.
Vérification côté serveur
Le worker Spectra :
- Lit
X-Spectra-Timestamp. Rejette si manquant ou plus vieux que 5 min. - Lit
X-Spectra-Signature. Rejette si manquant ou malformé. - Recalcule HMAC sur
<timestamp>.<body>avec le secret. - Compare en égalité à temps constant. Rejette en cas d'écart.
- Valide le schéma du corps (voir Schéma).
- Soumet au broker.
Erreurs courantes
- Signer le corps sans le préfixe de timestamp.
- Utiliser
==au lieu d'une comparaison à temps constant sur votre propre serveur (risque d'attaque par timing ; pas le problème de Spectra mais bon à faire si vous proxez notre webhook). - Envoyer du JSON dont le whitespace diffère de ce qui a été signé — signez toujours les exact bytes que vous POSTez.