Capturar uma NFS-e sob demanda pela chave de acesso
A captura normal é em lote: o ambiente nacional (ADN) distribui os documentos por NSU e nós entregamos a você. Quando você já tem a chave de acesso de uma NFS-e — o prestador mandou por e-mail, o cliente abriu um chamado, alguém consultou o portal da prefeitura — mas ela ainda não apareceu na sua listagem, você pode pedir a captura imediata daquele documento específico.
Base URL:
https://api.nfse.io· Auth: API Key com papelNota Fiscal (api.nfe.io)ouNFSeDist (dfe.nfe.io)— veja Autenticação.
Requisição
curl -X POST "https://api.nfse.io/v2/companies/{companyId}/inbound/nfse/fetch-by-access-key" \
-H "Authorization: SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "accessKey": "CHAVE_DE_50_DIGITOS" }'
| Campo | Obrigatório | Descrição |
|---|---|---|
accessKey | Sim | Chave de acesso da NFS-e — 50 dígitos, com dígito verificador válido |
A chamada é síncrona: consultamos a NFS-e diretamente na SEFIN Nacional, persistimos o documento e devolvemos os campos na própria resposta (200 OK), no mesmo formato dos itens da listagem de documentos. Não é preciso esperar webhook para saber o resultado.
A SEFIN só devolve o conteúdo de uma NFS-e quando o certificado da empresa que está pedindo aparece na nota como Prestador, Tomador ou Intermediário. Uma chave de acesso de nota alheia — mesmo válida — retorna 403 Forbidden com error: "AccessForbidden". Isso não é uma restrição da NFE.io e não há como contorná-la.
Resposta
{
"id": "<objectId>",
"companyId": "<companyId>",
"nsu": null,
"type": "serviceInvoice",
"accessKey": "<chave-50-digitos>",
"status": "Processed",
"webhookStatus": "Delivered",
"hasPdf": true,
"xmlSizeBytes": 9718
}
Os demais campos são os mesmos do item de listagem — provider, borrower, servicesAmount, serviceCode, issueCityCode, accrualOn, environment e afins.
nsu vem null. O NSU é atribuído pelo ambiente nacional na distribuição em lote, e essa nota foi obtida por consulta individual. Quando o lote trouxer a mesma NFS-e mais tarde, o nsu é preenchido. Trate nsu: null como um estado válido, não como erro: veja Tipos e enums.
webhookStatus: Delivered aqui não significa que houve um POST no seu endpointA captura sob demanda não publica webhook — os dados já vieram na resposta da chamada. O documento é gravado como se a entrega estivesse concluída justamente para não deixar uma entrega pendente que nunca aconteceria.
O webhook desse documento sai depois, quando o lote do ambiente nacional trouxer a mesma NFS-e: nesse momento o status de entrega é reiniciado e a notificação é despachada normalmente. Se você integra pelos dois caminhos, espere receber o webhook de uma nota que já tinha buscado sob demanda.
Idempotência
Se a NFS-e já foi capturada — pelo lote ou por uma chamada sob demanda anterior para a mesma chave — a resposta é 200 OK com o documento existente, sem nova consulta à SEFIN: não há risco de duplicar o documento nem de gerar tráfego extra contra o ambiente nacional.
A chamada em si continua sendo registrada como uso (veja Bilhetagem), então não a use em laço de polling.
Bilhetagem
Toda chamada a este endpoint gera um registro de uso da recepção de NFS-e, sob a ação GetDocByKey — inclusive as chamadas idempotentes, que do ponto de vista do registro são indistinguíveis de uma captura nova.
Além disso, quando o lote do ambiente nacional trouxer a mesma NFS-e mais tarde, essa chegada gera o registro normal de captura (ProcessDoc), como qualquer outro documento.
Quanto cada uma dessas ações custa — se custa — é definido no seu plano comercial: a recepção de NFS-e é bilhetada por ação, e o motor de bilhetagem precifica cada uma separadamente. Confirme com o time comercial antes de assumir que uma chamada é gratuita.
Erros
| Código | error | Causa | Ação |
|---|---|---|---|
400 | InvalidAccessKey | Chave ausente, com formato diferente de 50 dígitos ou dígito verificador inválido | Confirme a chave na origem (o DPS tem 42 dígitos e não serve aqui) |
403 | AccessForbidden | Sigilo fiscal — a empresa não é Prestador, Tomador nem Intermediário da nota | Não há remediação; confirme se a chave é de uma nota da sua empresa |
404 | CompanyNotFound | Empresa inexistente, inativa ou de outra conta | Verifique o companyId e se a captura está ativa |
404 | CertificateUnavailable | Empresa sem certificado registrado | Cadastre o certificado A1 antes de capturar |
404 | AdnNotFound | A SEFIN não conhece essa chave de acesso — ou o documento já está capturado e retido como histórico (ver nota acima) | Confirme a chave; notas muito recentes podem levar alguns minutos para indexar. Se a nota é antiga, verifique GET .../inbound/nfse/backfill |
502 | CertificateRejected | A SEFIN rejeitou o certificado da empresa | Verifique validade e se o CN corresponde ao CNPJ; renove se necessário |
503 | CertificateLookupFailed | Não foi possível verificar o certificado agora | Retente — o certificado pode existir; a consulta é que falhou |
503 | AdnUnavailable | SEFIN Nacional indisponível | Aguarde e retente |
Dois casos, com resultados opostos:
- A nota já foi capturada pelo lote e está retida como histórico (anterior ao corte, liberação não contratada): a chamada responde
404 AdnNotFound— o mesmo desfecho de uma chave desconhecida. É deliberado: se este endpoint devolvesse o documento que a listagem esconde, o histórico retido não estaria retido. - A nota é anterior ao corte mas nunca foi capturada: a captura acontece normalmente e o documento é entregue, sem ser classificado como histórico — fica visível na listagem como qualquer documento corrente. A razão é que você pediu aquela chave explicitamente, uma nota por vez.
Ou seja: a captura sob demanda não é um atalho para o histórico já retido, mas também não é bloqueada pela data de corte. Veja Ativar via API.
Quando usar (e quando não)
- ✅ Use para uma chave pontual que você já tem em mãos e precisa agora.
- ❌ Não use para varrer chaves em busca de notas: cada chamada nova é cobrada, e chave de nota alheia retorna
403. - ❌ Não use para "adiantar" o lote em volume. Para forçar um ciclo de captura da empresa inteira, use
fetch-now, que continua docurrentNsue não re-cobra o que já veio.
Veja também
- Ativar via API
- Integração REST
- Manutenção administrativa —
fetch-now, histórico e data de corte - Erros HTTP · Tipos e enums