Alertas por Slack, Teams e webhook

Além do e-mail, os alertas de falha e de normalização podem chegar ao Slack, ao Microsoft Teams ou ao seu próprio sistema (webhook). Cada canal recebe exatamente os mesmos alertas que o e-mail: um quando algo começa a falhar e outro quando volta a funcionar bem por vários minutos seguidos. Quedas que voltam dentro desse prazo fazem parte do mesmo alerta.

Disponível nos planos Básico e Profissional (até 5 canais ativos). Um administrador da empresa os configura na aba Canais, com a autenticação de dois fatores ativa.

Slack

  1. No Slack, crie um app (ou use um existente) e ative Incoming Webhooks.
  2. Escolha o canal e copie o endereço, que começa com https://hooks.slack.com/services/.
  3. Em Canais, escolha Slack, dê um nome, cole o endereço e clique em Adicionar. Use Enviar teste para conferir.

Microsoft Teams

O Teams recebe alertas pelo app Workflows (os antigos conectores do Microsoft 365 estão sendo descontinuados).

  1. No canal do Teams, abra Mais opções (…) → Workflows e escolha o modelo Send webhook alerts to a channel.
  2. Salve o fluxo e copie o endereço que ele fornece.
  3. Em Canais, escolha Microsoft Teams e cole o endereço.

Webhook para o seu sistema

Enviamos um POST com um JSON para um endereço https seu. Só aceitamos endereços públicos, não seguimos redirecionamentos e esperamos até 10 segundos pela resposta. Responda com qualquer código 2xx. Se responder 408, 429 ou 5xx, ou não responder a tempo, tentamos novamente com esperas crescentes durante 2 horas; qualquer outro 4xx encerra as tentativas daquele alerta.

Cabeçalhos:

  • Content-Type: application/json
  • X-Tecdex-Event: o tipo de evento.
  • X-Tecdex-Delivery: identificador do alerta. É o mesmo em cada nova tentativa: use-o para não processar o mesmo alerta duas vezes.
  • X-Tecdex-Signature: a assinatura, no formato t=<segundos unix>,v1=<assinatura>.

Exemplo de alerta de falha:

{
  "version": 1,
  "id": "6f1c2d1e-9a7b-4c51-8f0e-2b1f5c3a9d10",
  "event": "failure",
  "account": "acme",
  "system": "Site",
  "title": "ACME · Site com falha",
  "text": "ACME · Site com falha\nO que está falhando: Disponibilidade\nDesde: 26-10-2026 09:00 (UTC-03:00)\n…",
  "language": "pt",
  "url": "https://monitoreo.tecdex.net/c/acme/incidentes",
  "sent_at": "2026-10-26T12:00:05Z",
  "since": "2026-10-26T12:00:00Z",
  "recovery_wait_minutes": 10,
  "checks": [{"name": "Disponibilidade", "detail": "Não responde dentro do tempo limite"}]
}

Campos:

  • version: versão do formato (hoje 1). Podemos adicionar campos novos sem mudar a versão; nunca mudamos nem removemos os existentes.
  • id: identificador único do alerta (igual ao cabeçalho X-Tecdex-Delivery).
  • event: failure (começou a falhar), failure_update (outra verificação do mesmo sistema também falha), recovery (normalizado) ou test (mensagem de teste).
  • account: identificador da sua empresa. system: o sistema monitorado (vazio em test).
  • title e text: o alerta redigido no idioma do canal (language: es, en ou pt).
  • url: onde ver o detalhe no portal (pode ser null). sent_at: quando o enviamos (UTC).
  • Em failure e failure_update: since (desde quando falha, UTC), recovery_wait_minutes (minutos seguidos funcionando para avisar a normalização) e checks com name e detail (pode ser null).
  • Em recovery: started_at e ended_at (período com falhas, UTC), duration_seconds, failures (quedas no período) e checks com name e failures.

Verificar a assinatura

Ao criar o webhook mostramos uma única vez o seu segredo (começa com whsec_). Guarde-o no seu sistema. Se perder ou vazar, use Trocar segredo: o anterior deixa de funcionar.

Calcule HMAC-SHA256 com o segredo sobre o texto <t>.<corpo> (o corpo exatamente como chegou, sem remontar o JSON) e compare com v1. Rejeite também os alertas cujo t difira do seu relógio em mais de 5 minutos, para que ninguém possa repetir um antigo. Exemplo em Python:

import hashlib
import hmac
import time


def verificar(segredo, cabecalho, corpo, ahora=None, tolerancia=300):
    """segredo: o whsec_… · cabecalho: X-Tecdex-Signature · corpo: bytes exatamente como chegaram."""
    try:
        partes = dict(p.split("=", 1) for p in cabecalho.split(","))
        t = int(partes["t"])
    except (ValueError, KeyError):
        return False
    if abs((ahora or time.time()) - t) > tolerancia:
        return False
    esperado = hmac.new(segredo.encode(), f"{t}.".encode() + corpo, hashlib.sha256).hexdigest()
    return hmac.compare_digest(esperado, partes.get("v1", ""))

Entrar · Criar conta