Notificações
Webhook de mudança de regra
A regra foi publicada às 19h04; seu sistema soube às 19h06 — antes da próxima emissão sair errada. Um POST assinado chega ao seu endpoint a cada publicação de regra compatível com os seus filtros.
Como funciona
Você registra um endpoint HTTPS e, opcionalmente, filtros de tributo, UF de origem e UF de destino — filtro ausente é curinga (casa qualquer valor). Quando uma regra compatível é publicada, enviamos um POST com o corpo abaixo, assinado com o secret da inscrição.
| Item | Valor |
|---|---|
| Método | POST com Content-Type: application/json |
| Assinatura | header X-FinanSeed-Signature — HMAC-SHA256 (hex) do corpo bruto |
| Timeout | 10 segundos por tentativa |
| Retentativas | 3 tentativas com backoff exponencial + jitter para falhas transitórias (timeout, conexão, 5xx). Respostas 4xx não são retentadas — indicam configuração do seu endpoint. |
| Resposta esperada | Qualquer 2xx, o mais rápido possível |
Payload
{
"acao": "publicada",
"rule_id": "BR-MG-SP-NCM2202-ICMSST-v4.2",
"tributo": "icms_st",
"uf_origem": "SP",
"uf_destino": "MG",
"municipio": null,
"vigente_de": "2026-08-10"
}| Campo | Tipo | Descrição |
|---|---|---|
| acao | string | Hoje, sempre "publicada". Novos valores podem surgir — trate desconhecidos sem quebrar. |
| rule_id | string | ID semântico da versão publicada. |
| tributo | string | Discriminador do tributo (icms_st, iss, …). |
| uf_origem / uf_destino | string | null | Recorte geográfico da regra; null em regra federal/nacional. |
| municipio | string | null | Município, nos tributos municipais. |
| vigente_de | date | null | Início de vigência da versão publicada. |
Verificando a assinatura
O header X-FinanSeed-Signature é o HMAC-SHA256, em hexadecimal, do corpo bruto do POST com o secret da sua inscrição. Rejeite qualquer entrega cuja assinatura não confira — em comparação de tempo constante:
import hashlib, hmac
def assinatura_confere(secret: str, corpo_bruto: bytes, header: str) -> bool:
esperada = hmac.new(secret.encode(), corpo_bruto, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperada, header)
# no handler:
# corpo = await request.body() # bytes BRUTOS, antes de qualquer parse
# if not assinatura_confere(SECRET, corpo, request.headers["X-FinanSeed-Signature"]):
# return Response(status_code=401)const crypto = require("node:crypto");
// use express.raw({ type: "application/json" }) na rota do webhook
function assinaturaConfere(secret, corpoBruto, header) {
const esperada = crypto.createHmac("sha256", secret).update(corpoBruto).digest("hex");
const a = Buffer.from(esperada), b = Buffer.from(header ?? "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Boas práticas no seu endpoint
- Responda 2xx rápido e processe depois. Valide a assinatura, enfileire e retorne — o timeout é de 10 s e processamento síncrono pesado vira retentativa desnecessária.
- Seja idempotente. Retentativas podem entregar o mesmo evento mais de uma vez; use
rule_idcomo chave de deduplicação. - Ao receber, invalide seu cache do recorte afetado (tributo + UFs) — a próxima chamada ao
/v1/calculatejá responde pela regra nova. - Tenha o polling de segurança. O
GET /v1/changelogcobre qualquer janela em que seu endpoint tenha ficado fora — inclusive supersessões retroativas.
Como habilitar
A quantidade de endpoints varia por plano (Growth: 5 com retry; Scale/Enterprise: ilimitado com filtros). A gestão self-service de inscrições está chegando ao painel; até lá, envie URL do endpoint e filtros desejados para comercial@finanseed.com.br — a inscrição é criada e o secret é entregue por canal seguro.