Compatibilidade — SmartNFCe¶
O que o adaptador aceita, o que ele recusa e onde ele diverge do motor local. Onde não há linha nesta página, o comportamento é o do motor. A documentação dele continua valendo, e é essa a ideia.
Três veredictos aparecem nas tabelas:
| Veredicto | Significa |
|---|---|
| Compatível | Mesma forma de fio, mesmo comportamento |
| Ressalva | Funciona, com uma diferença que pode afetar o seu código |
| Fora | Não implementado nesta versão |
Cada linha compara dois lados de origens diferentes. O nosso lado roda aqui, e você pode conferi-lo contra este adaptador. O lado do motor vem de captura, e onde não houve captura esta página diz qual é o caso. Ver Formas sem captura.
Adaptador em desenvolvimento
As linhas desta página já são contrato. O adaptador ainda não foi lançado, então algo pode mudar até lá. Se mudar, muda aqui primeiro.
Autenticação¶
| Recurso | Veredicto | Observação |
|---|---|---|
| Nenhuma autenticação | Ressalva | O motor roda em localhost e não autentica. Na nuvem isso não é possível: exigimos o token OAuth2 de dispositivo que o equipamento já tem |
| Token de dispositivo já em campo | Compatível | Sem escopo novo, sem provisionamento, sem janela de migração |
| Empresa informada no corpo | Ressalva | Desnecessário: o vínculo vem do token |
401 HTTP em vez de erro em banda |
Ressalva | Exceção declarada à regra do 200. A autenticação é acréscimo nosso, e não faz parte do contrato do motor |
| Recusa genérica, sem dizer o que falhou | Ressalva | Deliberado: uma negativa de autenticação nunca revela qual verificação falhou |
pos_agent emitindo |
Fora | Só fiscal_box e smart_nfce alcançam os verbos fiscais. Um pos_agent recebe o mesmo 401 genérico de qualquer outra falha |
| Token sem o tipo de dispositivo | Ressalva | Recusado por segurança em vez de liberado. Nenhum escopo mudou. O dispositivo só precisa renovar o token uma vez |
| Emissor que custodia por várias empresas | Ressalva | Um fiscal_box ou smart_nfce custodia documentos de várias empresas, mas emite apenas pela empresa à qual está atribuído |
As duas linhas acima falam de dispositivos diferentes. Custódia flexível não concede
emissão: quem decide é o tipo do dispositivo. Se o seu equipamento custodia por várias
empresas e não é fiscal_box nem smart_nfce, o caso dele é a primeira linha.
Emissão¶
| Recurso | Veredicto | Observação |
|---|---|---|
POST /api/v1/nfce/xml/{uuid} com XML no corpo |
Compatível | |
uuid escolhido pelo cliente |
Compatível | É a chave de idempotência. Reenviar não gera segundo documento |
tpEmis decidido pelo cliente |
Compatível | Não decidimos contingência por você. É uma divergência deliberada em relação aos outros dialetos |
| Corpo "gordo" na autorização | Compatível | Os ~29 campos de identificação e telemetria, todos string. A telemetria tem uma ressalva na linha Tempo médio SEFAZ(ms) |
Tempo médio SEFAZ(ms) |
Ressalva | Repete o valor de Tempo comando(ms). Mede o comando inteiro, que inclui numeração, assinatura e gravação. Leia como teto, não como latência da SEFAZ |
| Corpo mínimo na rejeição | Compatível | Só cStat, xMotivo e diagnostico. É a forma do motor |
cStat como string na emissão |
Compatível | Reproduzido. Em outras rotas ele é int |
Erros de digitação nProto, dhRecibo, certificareExpiryCountdown |
Compatível | Reproduzidos verbatim, de propósito |
Sentinela -100 para contingência |
Compatível | |
Corpo malformado responde 200 em banda |
Compatível | Nunca um 422 |
| Campos desconhecidos no corpo | Compatível | Tolerados e ignorados, como no motor |
Agent version e agente |
Ressalva | Carregam a nossa identidade, não a do produto original. Um cliente que valida essa string precisa ajustar |
versao_base da pré-validação |
Ressalva | Reporta o nosso conjunto de regras, não a base do motor |
| Autocorreção de NCM | Fora | Adiada. O documento é recusado em vez de corrigido |
| Sinalização de CEST | Fora | Adiada |
Consulta¶
| Recurso | Veredicto | Observação |
|---|---|---|
GET /api/v1/nfce/authorization/status/{uuid} |
Compatível | |
GET /api/v1/nfce/{nNFouChave} por número ou chave |
Compatível | |
Sentinela -5 para uuid desconhecido |
Compatível | O sentinela é o mesmo nos dois casos, mas o texto não é: uuid not found e em processamento, consulte novamente significam coisas opostas para quem decide reenviar. Ver a divergência deliberada |
retConsSitNFe como JSON dentro de string |
Compatível | Nunca objeto aninhado |
verAplic em GET /api/v1/nfce/status_sefaz |
Ressalva | Hoje responde vazio. Ver o que fazer com o campo vazio |
verAplic responde vazio¶
O valor não chega ao adaptador, e preenchê-lo é trabalho ainda não feito.
De qualquer forma, não decida nada pela versão da aplicação da SEFAZ. O conselho vale com o campo vazio e continua valendo quando ele estiver preenchido.
Cancelamento¶
| Recurso | Veredicto | Observação |
|---|---|---|
POST /api/v1/nfce/cancelar por número ou chave |
Compatível | |
POST /api/v1/nfce/{chNFe}/cancel |
Compatível | justificativa obrigatória aqui, de 15 a 255 caracteres |
| Justificativa genérica quando omitida | Compatível | Reproduzido: Cancelamento a pedido do emitente da nota |
Campo protocolo no corpo |
Ressalva | Aceito para compatibilidade de fio, mas nunca necessário, porque nós já temos o protocolo dos nossos documentos |
| Cancelamento por substituição | Compatível | |
tpAutor no cancelamento por substituição |
Compatível | Aceita número e texto. As duas formas aparecem na documentação de origem, e o valor não altera o evento |
infEvento como JSON dentro de string |
Compatível |
Inutilização¶
| Recurso | Veredicto | Observação |
|---|---|---|
POST /api/v1/nfce/discard de uma faixa |
Compatível | |
GET /api/v1/nfce/inutilizacoes |
Compatível | |
cStat como string na resposta |
Compatível | |
cnpj, uf e tpAmb opcionais |
Ressalva | O motor exige os três. Aqui são opcionais, e quem responde por eles é o seu token. Ver quem garante esses valores |
Domínio de tpAmb |
Compatível | Quando enviado, só aceita 1 (produção) ou 2 (homologação). É o domínio que o motor publica. Qualquer outro valor é recusado na entrada, em vez de seguir para a SEFAZ |
ano obrigatório |
Compatível | O motor também o exige |
Formato de ano |
Compatível | Dois dígitos: 26, não 2026. É o tipo Tano do leiaute da NF-e, não uma restrição nossa. O ACBrAPI aceita as duas formas. Aqui 2026 é 422 |
Quem garante cnpj, uf e tpAmb¶
O motor exige os três no corpo do pedido. Aqui eles são opcionais, e essa relaxação é nossa.
Quem passa a responder por eles é o seu token. A empresa autenticada define o CNPJ, a UF e o ambiente que vão para a SEFAZ. O corpo não é a origem desses valores em nenhum dos casos, e omitir os campos não deixa nada em aberto.
Opcional não quer dizer não conferido. Enviados, os três continuam sendo checados contra a empresa autenticada, e um valor divergente é recusado.
DANFE¶
| Recurso | Veredicto | Observação |
|---|---|---|
POST /api/v1/nfce/danfepdf por número ou chave |
Compatível | |
| DANFE em base64 no corpo de emissão | Compatível | Inclusive na contingência, para o PDV conseguir imprimir |
| Paridade de bytes com o DANFE do motor | Fora | O PDF é gerado pelo nosso renderizador. O conteúdo fiscal é o mesmo e o documento é válido, mas os bytes não. Quem compara PDFs precisa parar |
| Configuração local de DANFE | Fora | Faz sentido só numa máquina local |
Contingência¶
| Recurso | Veredicto | Observação |
|---|---|---|
GET /api/v1/nfce/contingencia/pendentes |
Compatível | |
GET /api/v1/nfce/contingencia/resultado/{nNF} |
Compatível | Vocabulário em minúsculas. Ver os dois vocabulários |
GET /api/v1/nfce/processamentocontigencia |
Compatível | O erro de digitação está no caminho, e é reproduzido |
| Vocabulário capitalizado no relatório | Compatível | Nunca convertido no vocabulário minúsculo |
Sentinela -404 para documento não relevante |
Compatível | |
| Ligar e desligar contingência manualmente | Compatível | Interruptor de verdade: com ela ligada a emissão responde -100/tpEmis 9. O campo da resposta é status, sem acento |
| Durabilidade do interruptor | Ressalva | Não expira e só sai pelo disable correspondente. Não é um ajuste permanente: ver como saber em que modo você está |
| Desligar reprocessa a fila | Fora | Desligar só volta a emissão ao normal. Quem resolve a fila é o relatório de processamento |
| Contagens por ambiente | Ressalva | pendingContingencyInvoices e o relatório contam apenas o ambiente do endereço chamado. Não há visão consolidada |
O interruptor não é um ajuste permanente¶
No motor local o estado da contingência fica em disco e sobrevive a um reinício. Aqui a
garantia é outra. O interruptor não expira e só sai pelo disable correspondente, mas o
estado não tem a mesma durabilidade. Se ele for perdido, a emissão volta a tpEmis 1 sem
aviso.
A falha acontece na direção segura. O interruptor nunca fica ligado porém inerte. Perder o estado desliga a contingência de fato, e a emissão volta ao normal.
Nenhuma rota responde "a contingência está ligada?". Quem diz em que modo você está é o
tpEmis de cada emissão. Leia o tpEmis da resposta em vez de confiar no último enable
que você enviou.
Webhooks¶
| Recurso | Veredicto | Observação |
|---|---|---|
| Configuração única por empresa e ambiente | Compatível | Garantida no banco. Não há como registrar duas vezes e receber em duplicidade |
| Gravação parcial | Compatível | Só o que você envia muda. A primeira chamada precisa trazer a url |
secret somente escrita, lendo de volta *** |
Compatível | Enviar *** de volta significa não mudar. O laço ler/editar/gravar é seguro |
Configuração inexistente lê secret vazio |
Ressalva | Diferente do *** de uma configuração existente. Serve para saber se já há segredo definido |
| Assinatura HMAC-SHA256 sobre os bytes entregues | Compatível | Cabeçalho X-Webhook-Signature: sha256=<hex>. Opcional: sem segredo, sem assinatura |
retryMax e timeoutMs na configuração |
Ressalva | Aceitos, gravados e ecoados de volta, mas não obedecidos. A entrega segue a nossa escada fixa (1min/30min/1h/3h/24h). Um retryMax de 10 não produz dez tentativas |
| Catálogo de eventos | Compatível | Sete eventos, todos ativos. Ver Os sete eventos |
Tipo de nNF e cStat no corpo do webhook |
Ressalva | int no webhook (dados) e string no corpo da emissão. Os mesmos nomes de campo, tipos diferentes conforme a superfície. As duas formas são as do motor |
| Uma emissão, duas entregas | Ressalva | Um documento com avisos de pré-validação entrega nota_autorizada/nota_rejeitada e prevalidacao, em POSTs separados. O handler precisa ser idempotente por evento, não por documento |
contingencia_desativada sem pendentes |
Compatível | Assimétrico em relação a contingencia_ativada, de propósito |
timestamp do envelope |
Ressalva | Hora local da UF da empresa, sem indicação de fuso. Não interprete como UTC |
Formas sem captura¶
As formas desta tabela não vêm de nenhuma captura do motor. Nós as inferimos a partir do vocabulário dele. São exatamente os pontos em que o nosso contrato pode divergir do original sem que ninguém tenha como saber ainda. Se o seu PDV depende de alguma delas, confirme conosco antes.
| Forma | O que se sabe de fato |
|---|---|
A resposta de POST /api/v1/nfce/cancelar |
A mais frágil das seis. Não há evidência direta nenhuma. Ver de onde veio esta forma |
xMotivo do cStat 204 (Duplicidade de NF-e) |
O texto não aparece em lugar nenhum da documentação de origem. O corpo do 204 nunca foi observado |
| O corpo "gordo" da contingência | Não há captura. A única forma de origem é um exemplo curto, com cStat e nNF como int. Só o texto do xMotivo é literal |
As chaves de correcao_prevalidacao.aplicado[] |
Hoje a lista vem sempre vazia, então não afeta ninguém ainda. As chaves foram emprestadas de outro bloco e podem mudar quando ela começar a ser preenchida |
| A recusa de cancelamento e a recusa da pré-validação | Cantos que a documentação de origem não cobre |
Textos de recusa em português (Serviço indisponível, Cancelada por substituição e outros) |
Sem texto de origem |
A resposta de cancelar é uma escolha nossa¶
O exemplo que existe na documentação de origem está atribuído a /{chNFe}/cancel, e não a
POST /api/v1/nfce/cancelar. Separar as duas rotas é a leitura que respeita a captura, mas
é uma escolha nossa.
Uma divergência que é deliberada¶
Esta não é um palpite. É uma diferença que escolhemos manter, e ela existe para proteger você:
| Divergência | Por quê |
|---|---|
Um uuid em voo responde em processamento, consulte novamente, e não uuid not found |
Um PDV que lesse "não encontrado" reemitiria sob um uuid novo. Seriam dois documentos autorizados para uma venda só. Ver o que diverge e o que não |
O sentinela continua fiel, só o texto diverge¶
Um PDV que lê "não encontrado" conclui que a emissão não aconteceu. Ele reemite sob um
uuid novo, enquanto a primeira emissão ainda pode autorizar.
O sentinela -5 continua fiel, e só o texto diverge. Nunca trate as duas mensagens como o
mesmo caso.
Rotas do motor que o adaptador não serve¶
Estas rotas existem no motor e esta versão não as implementa. A resposta não é a do motor.
| Rota | Veredicto | Observação |
|---|---|---|
GET e POST /api/v1/email/config |
Fora | O motor envia o DANFE ao consumidor por SMTP configurado nele. O envio automático ainda não tem decisão nossa. Responde 404 |
GET /api/v1/nfce/laudo |
Fora | Laudo de conformidade do cadastro. Não responde 404. Ver o que ele responde |
GET e POST /api/v1/config/regras |
Fora | Ajuste local da severidade da pré-validação. Aqui valem as nossas regras, e não há superfície para alterá-las. Responde 404 |
POST /api/v1/nfe/danfe_preview |
Fora | Pré-visualização de NF-e modelo 55, que esta versão não emite. Responde 404 |
POST /api/v1/nfe/{chave44}/electronicCorrectionLetter |
Fora | Carta de Correção Eletrônica, exclusiva do modelo 55. Responde 404 |
POST /api/v1/nfe/{chave44}/manifestacao |
Fora | Manifestação do Destinatário, exclusiva do modelo 55. Responde 404 |
O laudo aponta para o Veraciti¶
A documentação do motor diz que o consolidado multi-PDV do laudo "é servido pela nuvem (Veraciti)". Ela nomeia o Veraciti como quem implementa essa rota, e esta versão não a serve.
GET /api/v1/nfce/laudo também não responde 404. O caminho tem um segmento só depois de
/api/v1/nfce/, então ele cai na consulta por número ou chave e recebe esta resposta:
O erro fala de chave de acesso porque veio da consulta, não do laudo. Se você depende do laudo, fale conosco antes de migrar.
Fora desta versão¶
Os verbos que só fazem sentido numa máquina física local não têm equivalente na nuvem:
| Recurso | Por que não |
|---|---|
| Impressão ESC/POS | Não há impressora do outro lado |
| Configuração de DANFE local | Idem |
| Cadastro local | A empresa e o certificado vivem na plataforma |
| Restauração de fábrica | Não há hardware para restaurar |
| Atualização automática do agente | O adaptador é atualizado por nós |
| Leitura de log local | Sem sistema de arquivos local para ler |