Autenticação da DC-e
As outras APIs da NFE.io autenticam com Authorization: <chave-de-api>. A DC-e não aceita esse formato — responde 401. É por isso que as bibliotecas oficiais (Node.js, PHP, Ruby), que autenticam por chave de API, ainda não atendem a DC-e.
A DC-e é o primeiro produto da NFE.io a autenticar por token JWT com escopos e papéis — um modelo diferente do padrão de chave de API usado no restante da plataforma. Veja Chaves de autenticação para o modelo usado nas demais APIs.
O token
Envie Authorization: Bearer <token>. O token precisa ter a audiência (aud) dfetech.contentdeclaration.api.
| Escopos que autorizam leitura | contentdeclaration:read, api.all.read, api.all.read-write |
| Escopos que autorizam emissão e cancelamento | contentdeclaration:write, api.all.read-write |
| Papéis aceitos (token de usuário, login no console) | dce:read para leitura, dce:issue para emissão |
api.all.read não autoriza emissãoEscopo de leitura não vira permissão de emitir documento fiscal — mesmo sendo um escopo "amplo" (api.all.*), ele só cobre a operação que o nome diz.
O endereço
A DC-e responde no host compartilhado da plataforma, o mesmo das demais APIs da NFE.io — a DC-e se distingue pelo caminho, não pelo host.
| Ambiente | Host |
|---|---|
| Produção | https://api.nfe.io |
| Homologação | https://api.nfse.nfe.one — endereço interno, só resolve com a VPN da NFE.io. Para homologar sua integração, fale com o suporte |
Assinatura e contribuinte: os dois vão na URL
Toda rota da DC-e carrega a assinatura e o contribuinte emitente, nesta ordem e em minúsculas:
/v1/subscriptions/{subscriptionId}/taxpayers/{taxpayerId}/contentdeclarations…
O isolamento dos documentos é pela assinatura do caminho — não pelo taxpayerId. São duas dimensões distintas: a assinatura diz de quem são os documentos; o taxpayerId diz qual contribuinte emite (a empresa cujo certificado assina o documento). Nenhum cabeçalho de assinatura é lido.
taxpayers na URL, companyId no corpoO recurso público é o contribuinte, e o serviço que o governa se chama tax-payers; dentro da plataforma o mesmo identificador se chama empresa. Por isso o campo companyId que a consulta em lista devolve carrega exatamente o valor que você pôs em {taxpayerId}.
| Tipo de token | O que o {subscriptionId} tem de ser |
|---|---|
Token de assinatura (client_credentials) | A assinatura do próprio token — outra, a resposta é 403 |
| Token de usuário (login no console) | Uma assinatura a que o usuário tem acesso — outra, a resposta é 403 |
O {subscriptionId} aceita o identificador com ou sem o prefixo sub_ (os dois são equivalentes).
O 403 de assinatura vem em application/problem+json com type https://docs.nfe.io/errors/dce/subscription-scope-undetermined — leia o type, não o texto, para distinguir esse caso de uma falta de escopo ou papel.
As formas anteriores — /v2/companies/{companyId}/ContentDeclarations… e /v2/subscriptions/{subscriptionId}/companies/{companyId}/… — respondem 404, e o cabeçalho X-Subscription-Id deixou de ser lido. Não há rota de compatibilidade, em host nenhum. A migração é trocar o caminho: nada mais no contrato mudou.