---
title: "Autenticação da DC-e"
description: "A DC-e usa token JWT (Bearer), não a chave de API da plataforma. Escopos, papéis e a assinatura na URL."
source_url: https://nfe.io/docs/documentacao/declaracao-de-conteudo-eletronica/autenticacao/
product: documentacao
last_updated: 2026-10-07
tags: ["dce", "autenticacao", "jwt", "bearer", "rbac"]
---

# Autenticação da DC-e

:::caution A chave de API da plataforma não funciona aqui
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](/documentacao/nossa-plataforma/chaves-de-autenticacao/) 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 |

:::caution `api.all.read` não autoriza emissão
Escopo 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.

:::note `taxpayers` na URL, `companyId` no corpo
O 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.

:::caution Se você integrou antes de 23/09/2026
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.
:::

## Veja também

- [Conceitos da DC-e](./conceitos.md)
- [Chaves de autenticação (demais APIs da plataforma)](/documentacao/nossa-plataforma/chaves-de-autenticacao/)
