Spectra
Parcourir la doc

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 :

  1. Lit X-Spectra-Timestamp. Rejette si manquant ou plus vieux que 5 min.
  2. Lit X-Spectra-Signature. Rejette si manquant ou malformé.
  3. Recalcule HMAC sur <timestamp>.<body> avec le secret.
  4. Compare en égalité à temps constant. Rejette en cas d'écart.
  5. Valide le schéma du corps (voir Schéma).
  6. 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.