Pular para conteúdo

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'
{
  "access_token": "eyJhbGciOi...",
  "token_type": "bearer",
  "scope": "nfce",
  "expires_in": 2592000
}

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 GET protegidos e 240 por minuto nas demais rotas protegidas. Aqui não existe nenhum deles. Não respondemos 429 nem 402, e não enviamos Retry-After, X-Retry-In nem os cabeçalhos x-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'
{ "@count": 1, "data": [ { "id": "8f3a1c02-...", "status": "autorizado" } ] }

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.IBSCBS em 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.
  • [ ] referencia enviada em toda emissão (opcional no contrato, mas é a sua proteção contra envio duplicado).