Stato · webhook
Iscriviti →Ricevi ogni incidente sul tuo endpoint.
POST JSON firmato ad ogni cambio di stato. Pronto per il tuo stack di osservabilità.
Eventi emessi
Tre tipi coprono il ciclo di vita dell'incidente.
incident.openedUn servizio passa a degradato, fuori servizio o manutenzione.incident.updatedNota pubblica aggiunta dal team durante l'incidente.incident.resolvedI servizi tornano operativi.
Header HTTP
Ogni richiesta porta le seguenti intestazioni.
POST /your/endpoint HTTP/1.1
Host: ops.example.com
Content-Type: application/json
User-Agent: Coffrify-Status-Webhook/1.0
X-Coffrify-Event: incident.opened
X-Coffrify-Timestamp: 1717248000
X-Coffrify-Signature: t=1717248000,v1=5b8c…f3a2Struttura del payload
Oggetto JSON compatto.
{
"type": "incident.opened",
"ts": "1717248000",
"incident": {
"id": "8c6a0c5e-…",
"slug": "eu-west-uploads-degraded",
"title": "Uploads dégradés en région eu-west",
"severity": "major",
"summary": "Latence accrue sur les uploads multipart depuis ~ 14:22 UTC.",
"affected_services": ["uploads", "api"],
"url": "https://status.coffrify.com/incident/eu-west-uploads-degraded"
},
"message": null
}Verifica della firma
HMAC-SHA256 su `timestamp.body`. Confronto a tempo costante. Drift > 5 min → rifiuta.
Node.js / TypeScript
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(rawBody: string, header: string, secret: string): boolean {
const m = /t=(\d+),v1=([0-9a-f]+)/.exec(header);
if (!m) return false;
const [, ts, sig] = m;
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(sig, "hex");
return a.length === b.length && timingSafeEqual(a, b);
}Python
import hmac, hashlib, time
def verify(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
ts, sig = parts.get("t"), parts.get("v1")
if not ts or not sig: return False
if abs(time.time() - int(ts)) > 300: return False
expected = hmac.new(
secret.encode(),
f"{ts}.{raw_body.decode()}".encode(),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, sig)Canale Slack
Per una URL hooks.slack.com ricevi un messaggio Block Kit:
- Header colorato per severità.
- Severità + stato.
- Riepilogo + ultimo aggiornamento.
- Pulsante all'incidente.
Consegna e retry
Atteso 2xx entro 6s. Nessun retry automatico.
2xx · 6 s · no retry