Guias
Webhooks
Um endpoint de webhook recebe o que as regras de alerta de um espaço de trabalho encaminham para ele: uma release bloqueada, um resultado aguardando uma pessoa, uma execução gerenciada que terminou, o alarme de um monitor de produção. Cada entrega é um corpo JSON assinado com o segredo do endpoint, para que o seu servidor possa verificar que veio do seu espaço de trabalho antes de agir.
Adicionar um endpoint
Na página Integrations do espaço de trabalho, um Owner ou Admin adiciona um webhook assinado com um nome e uma URL https pública na porta 443 ou 8443. A página então mostra o segredo de assinatura do endpoint, que começa com whsec_. Copie-o nesse momento: ele é armazenado criptografado e não é mostrado de novo. Para substituí-lo, exclua o endpoint e adicione-o novamente.
Depois, na página Alerts, escolha o endpoint como canal de uma ou mais regras. "Send a test" envia uma entrega oloproof.test e mostra o status que o seu servidor respondeu.
O que é enviado
{
"type": "oloproof.gate_blocked",
"id": "dlv_8c1f0a2b3c4d5e6f7a8b9c0d",
"created_at": "2026-10-26T14:03:00.000Z",
"workspace": "acme",
"rule": { "id": "rul_1a2b3c4d5e6f7a8b9c0d1e2f", "name": "Do not ship" },
"event": "gate_blocked",
"items": [
{
"project": "support",
"kind": "run",
"id": "run_20261026T140100_4f2a",
"release_action": "BLOCK",
"rules": [["faithfulness", "FAIL"]],
"href": "https://oloproof.com/app/workspaces/acme/projects/support/runs/run_20261026T140100_4f2a"
}
],
"more": 0
}Um item traz ids, os estados de decisão do motor, a ação de release, o estado e o desfecho de um job, o nível, o limite e o intervalo de um monitor como o motor os escreveu, e links. Nunca traz a entrada, a saída, a resposta esperada nem os rótulos de um caso. Uma entrega contém no máximo 50 itens; more conta os eventos além deles.
Verificar uma entrega
Toda entrega traz três cabeçalhos, no formato Standard Webhooks:
- webhook-id: o id da entrega, o mesmo em cada nova tentativa.
- webhook-timestamp: quando esta tentativa foi enviada, em segundos desde 1970.
- webhook-signature: v1, e o HMAC-SHA256 em base64 de id.timestamp.body, com chave nos bytes do segredo (a parte depois de whsec_, decodificada de base64).
Calcule a assinatura sobre o corpo bruto como recebido, compare-a em tempo constante e recuse um timestamp a mais de cinco minutos do seu relógio.
import base64, hashlib, hmac, time
def verify(secret: str, headers: dict, body: bytes) -> bool:
key = base64.b64decode(secret.removeprefix("whsec_"))
msg = f"{headers['webhook-id']}.{headers['webhook-timestamp']}.".encode() + body
expected = base64.b64encode(hmac.new(key, msg, hashlib.sha256).digest()).decode()
fresh = abs(time.time() - int(headers["webhook-timestamp"])) <= 300
given = [part.split(",", 1)[-1] for part in headers["webhook-signature"].split()]
return fresh and any(hmac.compare_digest(expected, sig) for sig in given)import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, headers, body) {
const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
const id = headers["webhook-id"], ts = headers["webhook-timestamp"];
const expected = createHmac("sha256", key).update(`${id}.${ts}.${body}`).digest("base64");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
return fresh && headers["webhook-signature"].split(" ").some((part) => {
const sig = Buffer.from(part.split(",").pop());
return sig.length === expected.length && timingSafeEqual(sig, Buffer.from(expected));
});
}As bibliotecas do Standard Webhooks verificam os mesmos cabeçalhos.
Entrega
Responda com qualquer status 2xx em até dez segundos. Qualquer outra coisa, inclusive um redirecionamento, é uma tentativa que falhou, repetida depois de 1, 5, 30, 120 e 360 minutos e então abandonada. Como uma resposta pode se perder depois que o seu servidor já agiu, a mesma entrega pode chegar duas vezes: use webhook-id para descartar uma repetição. Uma regra dispara no máximo uma vez por evento, então um id novo é uma entrega nova.
Antes de cada tentativa, o nome do endpoint é resolvido de novo, e a requisição só vai para um endereço público: endereços de loopback, privados, link-local, compartilhados, reservados e de metadados de nuvem são recusados, assim como formas IPv6 que contêm um deles. A conexão é feita com o endereço que foi verificado, e o certificado é verificado contra o nome.
Slack
Um endpoint do Slack é uma URL de incoming webhook. Ele recebe uma mensagem curta em inglês, uma linha por evento, com um link para cada resultado. O Slack não verifica os cabeçalhos de assinatura, que são enviados mesmo assim.