webhooks
Firmar requests
Cómo firmar tus POSTs al webhook con HMAC-SHA256 para que Spectra los verifique.
Cada POST a un webhook de Spectra debe llevar una firma HMAC-SHA256 del body. Requests sin firma o con firma inválida se rechazan con 401 Unauthorized.
La firma
X-Spectra-Signature: sha256=<hex>
X-Spectra-Timestamp: <unix-ms>
La firma se computa sobre <timestamp>.<body> (separados por punto):
import hmac, hashlib, time
secret = b"<bytes de tu 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",
}
Por qué el timestamp
Incluir el timestamp en el payload firmado liga el mensaje a un momento. Un mensaje capturado y replayado tras la ventana de 5 min falla la verificación — ver Replay.
Verificación server-side
El worker de Spectra:
- Lee
X-Spectra-Timestamp. Rechaza si falta o tiene > 5 min. - Lee
X-Spectra-Signature. Rechaza si falta o malformado. - Recomputa HMAC sobre
<timestamp>.<body>con el secret. - Compara con igualdad constant-time. Rechaza ante mismatch.
- Valida el schema del body (ver Schema).
- Envía al bróker.
Errores comunes
- Firmar el body sin el prefijo de timestamp.
- Usar
==en lugar de comparación constant-time en tu propio servidor (riesgo de timing attack; no es problema de Spectra pero vale la pena hacerlo bien si proxeas nuestro webhook). - Enviar JSON con whitespace distinto al firmado — firma siempre los bytes exactos que vas a hacer POST.