Guia de migração — ACBrAPI¶
1. Troque o endereço base¶
| Antes | Depois | |
|---|---|---|
| Produção | https://prod.acbr.api.br |
https://acbrapi.api.veraciti.com.br |
| Homologação | https://hom.acbr.api.br |
https://acbrapi-sandbox.api.veraciti.com.br |
| Token | https://auth.acbr.api.br |
o mesmo host da API |
O endereço do token muda de host, mas não de caminho: continua sendo
/realms/ACBrAPI/protocol/openid-connect/token. Se o seu cliente monta a URL do token a
partir de uma constante separada, essa constante passa a ser igual à da API.
A regra de ambiente é a mesma do provedor. O campo ambiente no corpo decide. O host de
produção aceita os dois valores, e o de homologação só aceita "homologacao".
2. Troque a credencial¶
O fluxo OAuth é idêntico. Continua sendo client_credentials, com client_id e
client_secret no corpo em application/x-www-form-urlencoded, ou em HTTP Basic, como a
sua biblioteca preferir:
curl -X POST \
https://acbrapi-sandbox.api.veraciti.com.br/realms/ACBrAPI/protocol/openid-connect/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials' \
-d 'client_id=exemplo-client-id' \
-d 'client_secret=exemplo-client-secret' \
-d 'scope=nfce'
expires_in continua sendo 30 dias. Duas diferenças a seu favor:
- Não aplicamos limite de taxa nem cota em rota nenhuma. O provedor publica três
limites: 4 requisições por hora no endpoint de token, 360 por minuto nos
GETprotegidos e 240 por minuto nas demais rotas protegidas. Aqui não existe nenhum deles. Não respondemos429nem402, e não enviamosRetry-After,X-Retry-Innem os cabeçalhosx-quota-*. Se o seu cliente já guarda o token em cache, nada muda. - Desativar uma credencial corta o acesso na hora, sem esperar o token expirar.
Envie o scope que o seu cliente já usa. O adaptador aceita todo o vocabulário do
provedor, inclusive empresa, conta, cnpj e cep, que nomeiam serviços fora deste
adaptador. O adaptador não recusa nem concede esses escopos.
O token recebe só os escopos que o adaptador atende. O campo scope da resposta lista
exatamente o que o token recebeu, então compare a resposta com o que você pediu.
As rotas de NFC-e exigem nfce. Sem esse escopo, a resposta é 403 insufficient_scope.
Omitir scope na requisição concede todos os escopos da credencial.
3. Ajuste o corpo¶
O corpo é a mesma árvore SEFAZ em JSON. Estes ajustes cobrem a maioria das integrações:
Adicione o grupo IBS/CBS em todo item. Obrigatório desde a transição de 2026. Sem ele, a SEFAZ rejeita com 1115. Ver Validação.
Confira a numeração. Por padrão o número é nosso e ide.nNF é ignorado. Se o seu
sistema é o dono da numeração, peça a credencial na faixa de numeração pelo cliente. Nesse
caso, nNF passa a ser obrigatório. Sem ele, a resposta é 422, e nunca um número
inventado por nós.
Confira o que é obrigatório. A referência declara o corpo da emissão, e a tabela
abaixo repete o que o esquema publicado já marca como obrigatório. Os campos são
recusados com 422 se faltarem, e a mensagem nomeia o caminho do campo
({"mensagem": "infNFe.ide.nNF: Campo obrigatório."}).
| Estrutura | Campos obrigatórios |
|---|---|
| Corpo da emissão | ambiente, infNFe |
infNFe |
ide, emit, det, pag |
Cada item de det |
prod, imposto |
pag |
detPag |
| Corpo da inutilização | ambiente, cnpj, ano, serie, numero_inicial, numero_final, justificativa |
Obrigatório aqui quer dizer presente, não preenchido: um pag sem detPag é recusado,
e um det sem imposto também. O conteúdo de cada grupo continua valendo pelas regras de
Validação.
Remova o que não é suportado. Somos estritos com campos desconhecidos: um grupo fora do
subconjunto é recusado pelo nome. A lista completa está na
página de compatibilidade. Os campos que o provedor aceita e que nós
derivamos do cadastro ou calculamos (emit além do CNPJ, total, cDV, cNF,
infNFeSupl, infRespTec) continuam sendo aceitos e ignorados. Você não precisa
tirá-los do seu gerador.
4. Ponta a ponta¶
Descrição obrigatória em homologação
Em homologação, a descrição do primeiro item precisa ser exatamente
NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL. Várias UFs
rejeitam (373) qualquer outra coisa. Em produção, use a descrição real do produto.
Emissão¶
curl -X POST https://acbrapi-sandbox.api.veraciti.com.br/nfce \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"ambiente": "homologacao",
"referencia": "PEDIDO1234",
"infNFe": {
"ide": {
"serie": 1,
"mod": 65,
"natOp": "VENDA AO CONSUMIDOR",
"tpNF": 1,
"indPres": 1,
"indFinal": 1,
"finNFe": 1,
"tpImp": 4,
"dhEmi": "2026-08-04T10:15:00-03:00"
},
"emit": { "CNPJ": "12345678000195" },
"det": [
{
"nItem": 1,
"prod": {
"cProd": "7891234",
"xProd": "NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL",
"NCM": "22021000",
"CFOP": "5102",
"uCom": "UN",
"qCom": 1,
"vUnCom": 10.00,
"vProd": 10.00
},
"imposto": {
"ICMS": { "ICMSSN102": { "orig": 0, "CSOSN": "102" } },
"IBSCBS": {
"CST": "000",
"cClassTrib": "000001",
"gIBSCBS": {
"vBC": 10.00,
"gIBSUF": { "pIBSUF": 0.10, "vIBSUF": 0.01 },
"gIBSMun": { "pIBSMun": 0.00, "vIBSMun": 0.00 },
"vIBS": 0.01,
"gCBS": { "pCBS": 0.90, "vCBS": 0.09 }
}
}
}
}
],
"pag": { "detPag": [ { "tPag": "01", "vPag": 10.00 } ] }
}
}'
A resposta já é o desfecho, e não há fila:
{
"id": "8f3a1c02-5d47-4a2e-9b10-6e2f7c4d8a31",
"ambiente": "homologacao",
"created_at": "2026-08-04T13:15:04.512348+00:00",
"status": "autorizado",
"referencia": "PEDIDO1234",
"data_emissao": "2026-08-04T10:15:00-03:00",
"modelo": 65,
"serie": 1,
"numero": 12,
"tipo_emissao": 1,
"valor_total": 10.0,
"chave": "41260812345678000195650010000000121000000011",
"autorizacao": {
"status": "registrado",
"codigo_status": 100,
"motivo_status": null,
"mensagem": null,
"numero_protocolo": "141260000000123",
"data_recebimento": "2026-08-04T13:15:06+00:00",
"chave_acesso": "41260812345678000195650010000000121000000011"
}
}
Guarde o id: ele identifica o documento em todas as outras rotas.
Reenvio após uma recusa¶
O reflexo de reenviar o mesmo pedido não funciona aqui
Cada referencia responde sempre pelo mesmo documento. Se a emissão foi recusada, pela
SEFAZ ou pelo próprio adaptador, reenviar com a mesma referencia devolve
exatamente a resposta anterior, com o mesmo id e o mesmo 200. Nenhuma nova
tentativa chega à SEFAZ.
Para tentar de novo, corrija o corpo e envie com uma referencia nova. A recusa diz
isso no próprio corpo, em autorizacao.mensagem:
{
"autorizacao": {
"status": "rejeitado",
"codigo_status": 539,
"mensagem": "Corrija o documento e reenvie com uma nova referência. Uma nova requisição com a mesma referência apenas repete este resultado."
}
}
Quando a transmissão não chega ao fim, a mensagem também confirma o que acontece com a numeração:
Emita novamente com uma nova referência; o número informado continua disponível. Uma nova requisição com a mesma referência apenas repete este resultado.
Na numeração gerenciada por você, o nNF recusado continua disponível. A SEFAZ não
registra nada sob um número rejeitado. Só saem de circulação os números efetivamente
consumidos. A tabela completa está em
Quando um número seu pode ser reutilizado.
Este é um ponto em que os dois dialetos divergem de propósito: no FocusNFE, reenviar a mesma
ref depois de um erro_autorizacao é o caminho de correção do provedor. Aqui não há
equivalente. Ver Reenvio da mesma referência.
Consulta¶
curl https://acbrapi-sandbox.api.veraciti.com.br/nfce/8f3a1c02-5d47-4a2e-9b10-6e2f7c4d8a31 \
-H "Authorization: Bearer $TOKEN"
Buscar pela sua própria referência continua sendo pela listagem, com os parâmetros obrigatórios do provedor:
curl -G https://acbrapi-sandbox.api.veraciti.com.br/nfce \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode 'cpf_cnpj=12345678000195' \
--data-urlencode 'ambiente=homologacao' \
--data-urlencode 'referencia=PEDIDO1234' \
--data-urlencode '$inlinecount=true'
Cancelamento¶
Dentro de 30 minutos da autorização, com justificativa de 15 a 255 caracteres:
curl -X POST \
https://acbrapi-sandbox.api.veraciti.com.br/nfce/8f3a1c02-5d47-4a2e-9b10-6e2f7c4d8a31/cancelamento \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "justificativa": "Cancelamento a pedido do consumidor" }'
Corpo vazio também funciona: como no provedor, preenchemos uma justificativa padrão.
{
"id": "48291",
"ambiente": "homologacao",
"status": "registrado",
"autor": { "cpf_cnpj": "12345678000195" },
"chave_acesso": "41260812345678000195650010000000121000000011",
"data_evento": "2026-08-04T13:31:22+00:00",
"numero_sequencial": 1,
"data_recebimento": "2026-08-04T13:31:22+00:00",
"codigo_status": 135,
"motivo_status": "Evento registrado e vinculado a NF-e",
"numero_protocolo": "141260000000456",
"tipo_evento": "110111",
"justificativa": "Cancelamento a pedido do consumidor"
}
O vocabulário de status de evento é diferente do de documento: registrado, não
autorizado.
Download do XML¶
curl https://acbrapi-sandbox.api.veraciti.com.br/nfce/8f3a1c02-.../xml \
-H "Authorization: Bearer $TOKEN" -o documento.xml
Não cobramos por download repetido. A regra de "primeiro download grátis" do provedor não existe aqui.
Checklist¶
- [ ] Endereço base trocado, incluindo o do endpoint de token.
- [ ] Credencial nova, com escopo
nfce, e token em cache. - [ ] Grupo
imposto.IBSCBSem todo item. - [ ] Decisão de numeração tomada: nossa (padrão) ou sua (credencial específica).
- [ ] Campos fora do subconjunto removidos. Teste em homologação e leia os
422. - [ ] Descrição de homologação aplicada no ambiente de testes.
- [ ]
referenciaenviada em toda emissão (opcional no contrato, mas é a sua proteção contra envio duplicado).