Prévia: a API abre junto com o painel.
Gatilhos de pagamento
Recebeu, emitiu. Um gatilho é um endereço de entrada só seu: o seu sistema avisa que um pagamento foi confirmado e o NFSeIA emite a nota fiscal de serviço a partir de um modelo, sem ninguém clicar. O mesmo pagamento nunca gera duas notas.
Serve para qualquer meio de pagamento: no ponto do seu sistema em que o pagamento é confirmado (o aviso do seu banco ou da sua plataforma de cobrança), mande o aviso para o gatilho. Conectores prontos para os meios de pagamento mais usados chegam depois do lançamento.
1. Crie o gatilho com o modelo da nota
O modelo diz como a nota sai. Tomador e valor podem ser fixos ou vir em cada aviso; o resto de
serviço e impostos, se você não informar, vem dos padrões da empresa. A origem diz de onde vêm os
pagamentos: um nome curto para o seu sistema de cobrança e a conta nele. Ela entra na identidade de
cada nota e não muda depois da criação.
curl -X POST https://api.nfseia.com.br/v1/gatilhos \
-H "Authorization: Bearer $NFSEIA_CHAVE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"nome": "Assinaturas do sistema",
"origem": { "provedor": "meu-sistema", "conta": "principal" },
"modelo": {
"usar_valor_do_aviso": true,
"tomador": null,
"servico": { "descricao": "Assinatura mensal do sistema de gestão" },
"valores": {}
}
}'A resposta traz o url do gatilho e o segredo (gsec_...), este uma única vez:
{
"id": "gat_01JC91D3F6H9K2M5P8R1T4W7Y0",
"origem": { "provedor": "meu-sistema", "conta": "principal" },
"url": "https://api.nfseia.com.br/v1/gatilhos/gat_01JC91D3F6H9K2M5P8R1T4W7Y0/eventos",
"segredo": "gsec_6fQ2xN8vR1kT4mW7zB0cE3hJ5",
"status": "ativo"
}usar_valor_do_aviso: true: o valor de cada nota vem do aviso. Comfalse, valemodelo.valores.valor_servico, o mesmo para todo pagamento.tomador: null: o tomador vem em cada aviso. Para um cliente só, fixe o tomador no modelo.- No MVP, gatilho não aceita intermediário nem
retido_pelo_intermediario.
2. Mande o aviso quando o pagamento for confirmado
O endereço do gatilho é público e não usa chave de API: o aviso vale só com a assinatura
NFSeIA-Assinatura, o HMAC-SHA256 de {t}.{corpo} com o segredo do gatilho, igual à dos
webhooks, no sentido contrário.
Em Node:
import { createHmac } from 'node:crypto';
export async function avisarPagamento(pagamento) {
const corpo = JSON.stringify({
pagamento_id: pagamento.id,
valor: pagamento.valor, // "89.90"
pago_em: pagamento.pagoEm, // "2026-11-05T16:42:07-03:00"
tomador: { documento: pagamento.cliente.documento, nome: pagamento.cliente.nome, email: pagamento.cliente.email },
});
const t = Math.floor(Date.now() / 1000);
const v1 = createHmac('sha256', process.env.NFSEIA_SEGREDO_GATILHO).update(`${t}.${corpo}`).digest('hex');
const resposta = await fetch(process.env.NFSEIA_URL_GATILHO, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'NFSeIA-Assinatura': `t=${t},v1=${v1}` },
body: corpo,
signal: AbortSignal.timeout(35_000),
});
return { status: resposta.status, nota: await resposta.json() };
}Em Python:
import hashlib
import hmac
import json
import os
import time
import requests
def avisar_pagamento(pagamento: dict) -> requests.Response:
corpo = json.dumps({
"pagamento_id": pagamento["id"],
"valor": pagamento["valor"], # "89.90"
"pago_em": pagamento["pago_em"],
"tomador": pagamento["tomador"],
})
t = str(int(time.time()))
v1 = hmac.new(os.environ["NFSEIA_SEGREDO_GATILHO"].encode(), f"{t}.{corpo}".encode(), hashlib.sha256).hexdigest()
return requests.post(
os.environ["NFSEIA_URL_GATILHO"],
data=corpo.encode(),
headers={"Content-Type": "application/json", "NFSeIA-Assinatura": f"t={t},v1={v1}"},
timeout=35,
)Assine o corpo exatamente como ele vai ser enviado: qualquer espaço a mais muda a assinatura. Gere
t na hora de cada envio, inclusive nas novas tentativas: o NFSeIA recusa t a mais de 5 minutos do
horário atual, no passado ou no futuro.
3. O que volta
A resposta é a mesma da emissão pela API:
201: nota autorizada.200: este pagamento já tinha nota; volta a mesma, nada é emitido.202: a SEFIN demorou; a nota ficapendentee o webhook avisa quando sair.400 dados_invalidosou422 nota_rejeitada: corrija e mande o aviso de novo.401 assinatura_invalida: assinatura errada ou comta mais de 5 minutos do horário atual.429: limite de avisos. O limite por IP vale antes de conferir a assinatura (inclusive para assinatura inválida); depois dela, vale o limite por gatilho e o de emissões da empresa.409 estado_invalido: o gatilho está pausado. Mande de novo depois de reativar.
Uma nota por pagamento
A identidade da nota é pagamento:{provedor}:{conta}:{pagamento_id}, com provedor e conta da
origem do gatilho, e é reservada antes de qualquer envio à SEFIN. Gatilhos com a mesma origem
compartilham a identidade. Pode mandar o mesmo aviso quantas vezes quiser, por um ou por outro
gatilho (o seu sistema tentou de novo, o aviso chegou duas vezes do seu banco): a nota é uma só. Por
isso o pagamento_id precisa ser o id do pagamento, não do cliente nem do pedido, se um pedido
tiver mais de um pagamento.
O prefixo pagamento: é reservado: a emissão manual pela API recusa referência que comece com ele
(400 referencia_reservada).
Cuidar do gatilho
PATCH /gatilhos/{id}com"status": "pausado"para de emitir na hora;"ativo"volta.POST /gatilhos/{id}/rotacionar-segredotroca o segredo. Com{"modo": "normal"}, o anterior vale por mais 24 horas (no máximo um anterior por vez); com{"modo": "emergencia"}, é revogado na hora.DELETE /gatilhos/{id}apaga o endereço. Notas já emitidas não mudam.
Gatilho criado com chave de teste emite no ambiente de teste. Comece por ele.