API e Integrações
Conecte seu ERP, e-commerce ou sistema legado à plataforma FinzioFiscal via API REST de alta performance.
Portal do Desenvolvedor
Acesse o menu Desenvolvedor no topo ou lateral da plataforma para gerenciar suas credenciais de integração, consultar logs de chamadas e visualizar a especificação interativa Swagger/OpenAPI.
Criando Credenciais de Integração
Para que um sistema externo envie ou consulte notas fiscais, você deve criar um par de chaves de API:
- 1Na aba Credenciais de API, clique no botão Criar Credencial.
- 2Defina um nome de identificação (ex: “ERP Protheus Produção” ou “Loja Virtual Shopify”) e escolha o ambiente (Produção ou Homologação).
- 3Copie o Client ID e o Client Secret gerados.
O Client Secret é exibido apenas uma vez no momento da criação. Guarde-o em local seguro (como variáveis de ambiente do seu backend). Caso perca o segredo, será necessário gerar uma nova credencial.
Autenticação nas requisições
A API tem duas formas de autenticar, para dois usos diferentes. Não as confunda:
1. Credencial de integração (Client ID e Client Secret), para sistemas externos (ERP, e-commerce). Vale nas rotas /integration/* e usa HTTP Basic: o Client ID é o usuário e o Client Secret é a senha.
2. Login de usuário (token JWT), para o que a tela também faz: listar e baixar documentos, relatórios e cadastros, com as permissões do usuário. Chame POST /auth/login com e-mail e senha e envie o token recebido:
Sessão de API: sem renovação automática
O login feito diretamente pela API cria uma sessão de API. Ela é diferente da sessão da tela: não recebe refreshToken, vale até o token expirar e é encerrada sozinha se ficar um período sem requisições (30 minutos por padrão). Quando isso acontecer, a API responde 401 e basta fazer login de novo.
Para encerrar a sessão antes, chame POST /auth/logout. A sessão de API não derruba a sessão da tela do mesmo usuário, e o contrário também vale. Em Sessões & Histórico de Login ela aparece com o canal “API”.
X-Client-Channel: web) é única por usuário: entrar em outro dispositivo encerra a anterior. Integrações não precisam enviar esse cabeçalho.Referência interativa e coleção Postman
A referência completa da API (Swagger/OpenAPI) fica em /docs, e o mesmo documento em JSON em /docs/json. A coleção Postman, gerada desse mesmo documento, pode ser baixada em /docs/postman ou na área de chaves de API. Importe a coleção e preencha as variáveis: baseUrl; clientId e clientSecret para as rotas de integração. Para as demais, execute a requisição de login da coleção, que guarda o token na variável tokenSessao automaticamente.
Principais Endpoints REST
Emissão de NF-e ou NFC-e pela integração. Recebe o JSON com destinatário, itens e tributação, assina, transmite à SEFAZ e devolve a chave de acesso e o protocolo. Credencial de integração.
Emissão em lote: envia um arquivo ZIP com vários documentos, cada um validado como na emissão unitária. Credencial de integração.
Emissão assíncrona com o mesmo JSON da rota síncrona. Responde 202 na hora com o commandId, e a transmissão segue em fila, na ordem de chegada por CNPJ emitente, com nova tentativa automática e consulta à SEFAZ antes de reenviar. Repetir a mesma idempotencyKey com o mesmo corpo devolve o comando com 200; com outro corpo, 409. O andamento sai em GET /integration/emission-commands/:id ou /by-idempotency-key/:key. Credencial de integração.
Consulta uma emissão pela chave de acesso. O XML e o DANFE saem em /integration/nfe-emissions/:id/xml e /:id/danfe. Credencial de integração.
Lista as NF-e recebidas, com filtros por período de emissão, CNPJ, status, número e chave de acesso, e paginação. Existem também /ctes e /nfse. Login de usuário.
Download do XML original de um documento recebido (kind é nfe, cte ou nfse). Login de usuário.
Registra e transmite o evento prévio de EPEC (Emissão em Contingência) à SEFAZ Virtual RS quando o autorizador normal está indisponível, liberando a operação comercial da empresa. A nota definitiva sai assim que a SEFAZ normal volta, com a mesma chave de acesso do evento prévio. Login de usuário.
Baixa XMLs em lote de um tipo por chamada (tipo), filtrados por chave, número, CNPJ ou período, com o XML em base64 na resposta paginada. As datas aceitam AAAA-MM-DD, DD.MM.AAAA e DD/MM/AAAA; data inválida responde 400. Na API, os filtros informados se combinam (chave e período, por exemplo, valem juntos). Login de usuário.
/docs para testar as chamadas e ver o esquema completo de cada campo.Webhooks: o Finzio avisa o seu sistema
Em vez de consultar a API de tempos em tempos, cadastre em Administração, Webhooks o endereço do seu sistema e escolha os eventos. O Finzio faz um POST com JSON a cada evento. O endereço precisa ser público e, em produção, usar HTTPS. Redes internas e redirecionamentos são recusados.
Eventos
document.received: Um documento novo (NF-e, CT-e ou NFS-e) entrou no acervo da empresa.manifestation.registered: A SEFAZ registrou uma manifestação do destinatário ou um desacordo de CT-e.emission.authorized: Uma NF-e, NFC-e, CT-e ou MDF-e emitida foi autorizada pela SEFAZ.emission.canceled: Uma NF-e ou NFC-e emitida foi cancelada.emission.corrected: Uma carta de correção foi registrada.emission.command.succeeded: Um comando de emissão assíncrona chegou ao resultado fiscal.emission.command.failed: Um comando esgotou as tentativas sem resposta da SEFAZ.
Corpo
O corpo traz só ids, chave de acesso, códigos e datas. XML e DANFE saem pela API autenticada, pelo link em data.links. Campo novo pode aparecer a qualquer momento: ignore o que não conhecer. Mudança de significado sai numa versão nova do evento (eventVersion).
{
"id": "5f0c6c1e-8a4e-4c4b-9a53-1f1f3a0d2b77",
"eventType": "document.received",
"eventVersion": 1,
"occurredAt": "2026-09-28T12:00:00.000Z",
"tenantId": "…",
"companyId": "…",
"companyCnpj": "11222333000181",
"aggregate": { "type": "received-document", "id": "3526…6785" },
"data": {
"documentId": "…",
"documentKind": "NFE",
"accessKey": "3526…6785",
"issuedAt": "2026-09-27T18:20:00.000Z",
"links": { "self": "/fiscal-documents/nfe/…" }
}
}Cabeçalhos e verificação
X-Finzio-Event-Id: id do evento, igual aoiddo corpo e o mesmo em toda reentrega. Guarde e descarte o que já processou.X-Finzio-Event-Type: o tipo do evento.X-Finzio-Timestamp: segundos Unix do envio. Recuse o que estiver a mais de 5 minutos do seu relógio: é o que impede alguém de reenviar uma requisição capturada.X-Finzio-Signature:v1=seguido do HMAC-SHA256, em hexadecimal, detimestamp.corpocom o segredo da assinatura.
import { createHmac, timingSafeEqual } from 'node:crypto';
// body: o corpo CRU da requisição, antes de qualquer JSON.parse.
export function webhookValido(headers, body, segredo) {
const ts = Number(headers['x-finzio-timestamp']);
if (!Number.isInteger(ts) || Math.abs(Date.now() / 1000 - ts) > 300) return false;
const esperado = Buffer.from(
'v1=' + createHmac('sha256', segredo).update(ts + '.' + body).digest('hex'),
);
// Na rotação de segredo chegam duas assinaturas separadas por vírgula.
return String(headers['x-finzio-signature'])
.split(',')
.some((s) => {
const recebido = Buffer.from(s.trim());
return recebido.length === esperado.length && timingSafeEqual(recebido, esperado);
});
}Entrega, repetição e ordem
Responda 2xx em até 10 segundos e processe depois, em fila. Qualquer outro retorno, ou a falta de resposta, gera nova tentativa: 30 segundos, dobrando até 6 horas, com uma variação aleatória, até 8 tentativas. Depois disso a entrega fica como falha na tela, de onde pode ser reenviada com o mesmo event id. A entrega é ao menos uma vez: o mesmo evento pode chegar duas vezes, e eventos de documentos diferentes podem chegar fora de ordem. Para o mesmo documento, use occurredAt.