Pular para o conteúdo

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.

ItemValor
MétodoPOST com Content-Type: application/json
Assinaturaheader X-FinanSeed-Signature — HMAC-SHA256 (hex) do corpo bruto
Timeout10 segundos por tentativa
Retentativas3 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 esperadaQualquer 2xx, o mais rápido possível

Payload

POST no seu endpoint
{
  "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"
}
CampoTipoDescrição
acaostringHoje, sempre "publicada". Novos valores podem surgir — trate desconhecidos sem quebrar.
rule_idstringID semântico da versão publicada.
tributostringDiscriminador do tributo (icms_st, iss, …).
uf_origem / uf_destinostring | nullRecorte geográfico da regra; null em regra federal/nacional.
municipiostring | nullMunicípio, nos tributos municipais.
vigente_dedate | nullIní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:

Python (FastAPI/Flask)
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)
Node.js (Express)
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_id como chave de deduplicação.
  • Ao receber, invalide seu cache do recorte afetado (tributo + UFs) — a próxima chamada ao /v1/calculate já responde pela regra nova.
  • Tenha o polling de segurança. O GET /v1/changelog cobre 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.