Como consultar as certidões de um fornecedor por API?
Script pronto em Python: CND Federal, CNDT e CRF do FGTS de uma lista de CNPJs, com a situação, a validade e o PDF de cada certidão.
Atualizado em
Três chamadas por CNPJ: /api/consultar-cnd-federal, /api/consultar-cndt e /api/consultar-crf-fgts. O script desta página lê uma lista de CNPJs, grava uma planilha com a situação e a validade de cada certidão e salva os PDFs numa pasta.
- Custo: 1 consulta por certidão, 3 por CNPJ: de R$ 0,075 a R$ 2,01 por fornecedor, conforme o plano (tabela).
- Sem PDF, mais barato:
/api/certidoes-todasdevolve as três situações em 1 consulta. - Para testar: a API pede plano ou recarga, a partir de R$ 19,99/mês. No painel, sem programar, são 10 consultas grátis por mês.
- Sem certificado digital: basta o CNPJ.
- Comece: crie a conta e a chave de API.
O que cada certidão prova
| Certidão | Órgão | Prova | Validade |
|---|---|---|---|
| CND Federal | Receita Federal e PGFN | Tributos federais, contribuições previdenciárias e Dívida Ativa da União | 180 dias |
| CNDT | TST | Débitos trabalhistas | 180 dias |
| CRF do FGTS | Caixa | Regularidade do empregador no FGTS | 30 dias |
A CND estadual (ICMS) tem rota própria, por UF: Consultar CND.
Antes de começar
- Python 3.9 ou mais novo. O SDK oficial não tem dependências.
- A chave de API na variável de ambiente
FISCALAPI_API_KEY. - Um arquivo
fornecedores.csvcom a colunacnpj. Use o CNPJ da matriz: a CND Federal é emitida para a matriz e vale para as filiais.
pip install fiscalapi-br
export FISCALAPI_API_KEY="fapi_sua_chave_aqui"O script
Salve como certidoes.py:
"""CND Federal, CNDT e CRF do FGTS de uma lista de CNPJs, com os PDFs."""
import base64
import csv
import os
import sys
import time
from fiscalapi_br import (
APIConnectionError,
AuthenticationError,
BadRequestError,
FiscalAPI,
InsufficientBalanceError,
RateLimitError,
ServerError,
)
ENTRADA = "fornecedores.csv" # coluna "cnpj"
SAIDA = "certidoes.csv" # uma linha por certidão; é também o checkpoint
PASTA_PDF = "pdfs"
COLUNAS = ["cnpj", "certidao", "status", "validade_iso", "numero", "pdf", "erro"]
# Segundos entre chamadas, pelo limite por minuto do plano.
PAUSA = {"lite": 12.0, "starter": 3.0, "pro": 1.0, "enterprise": 0.5}
PLANO = "starter"
def limpar(valor: str) -> str:
return "".join(c for c in valor if c.isalnum()).upper()
def ja_feitas() -> set[tuple[str, str]]:
if not os.path.exists(SAIDA):
return set()
with open(SAIDA, encoding="utf-8", newline="") as f:
return {(linha["cnpj"], linha["certidao"]) for linha in csv.DictReader(f)}
def gravar(linha: dict) -> None:
novo = not os.path.exists(SAIDA)
with open(SAIDA, "a", encoding="utf-8", newline="") as f:
w = csv.DictWriter(f, fieldnames=COLUNAS)
if novo:
w.writeheader()
w.writerow(linha)
def consultar(chamada, cnpj: str) -> dict:
"""Chama a rota e espera se a certidão ainda estiver sendo emitida."""
for _ in range(4):
resp = chamada(cnpj=cnpj)
if resp["source_status"].get("error_code") != "EM_PROCESSAMENTO":
return resp
# O tempo sugerido vem no header Retry-After, que o SDK não expõe: 30 s cobre.
time.sleep(30)
return resp
def main() -> None:
api = FiscalAPI() # lê FISCALAPI_API_KEY; repete sozinho em 429 e 5xx
certidoes = {
"cnd_federal": api.consultar_cnd_federal,
"cndt": api.consultar_cndt,
"crf_fgts": api.consultar_crf_fgts,
}
os.makedirs(PASTA_PDF, exist_ok=True)
with open(ENTRADA, encoding="utf-8-sig", newline="") as f: # utf-8-sig: aceita CSV salvo pelo Excel
cnpjs = list(dict.fromkeys(limpar(linha["cnpj"]) for linha in csv.DictReader(f)))
feitas = ja_feitas()
for cnpj in filter(None, cnpjs):
for nome, chamada in certidoes.items():
if (cnpj, nome) in feitas:
continue
inicio = time.monotonic()
linha = {"cnpj": cnpj, "certidao": nome}
try:
resp = consultar(chamada, cnpj)
except InsufficientBalanceError as e:
print(f"Parei no {cnpj}: {e.message}. Rode de novo depois de recarregar.")
sys.exit(2)
except AuthenticationError as e:
print(f"Chave recusada: {e.message}")
sys.exit(3)
except BadRequestError as e:
gravar({**linha, "erro": e.code}) # pedido recusado: não repete
continue
except RateLimitError as e:
time.sleep(e.retry_after or 60) # fica para a próxima rodada
continue
except (ServerError, APIConnectionError):
continue # fica para a próxima rodada
codigo = resp["source_status"].get("error_code") or ""
r = resp.get("result")
if codigo in ("CNPJ_INVALIDO", "CPF_INVALIDO"):
# Vem em HTTP 200, sem exceção. Não é cobrado e não adianta repetir.
gravar({**linha, "erro": codigo})
elif not r or r["status"] == "erro":
# O órgão não respondeu ou recusou o pedido. Não é cobrado e não é gravado:
# entra de novo na próxima rodada. A mensagem diz o motivo.
print(cnpj, nome, codigo or (r or {}).get("status_raw", ""))
else:
if r.get("pdf_base64"):
linha["pdf"] = os.path.join(PASTA_PDF, f"{cnpj}_{nome}.pdf")
with open(linha["pdf"], "wb") as f:
f.write(base64.b64decode(r["pdf_base64"]))
gravar({**linha, "status": r["status"], "validade_iso": r.get("validade_iso", ""),
"numero": r.get("protocolo", "")})
espera = PAUSA[PLANO] - (time.monotonic() - inicio)
if espera > 0:
time.sleep(espera)
print("Fim. O que não entrou em certidoes.csv é consultado se você rodar de novo.")
if __name__ == "__main__":
main()Rode com python certidoes.py. Ajuste PLANO para o seu plano.
Como ler o resultado
O campo status de cada certidão:
negativa: regular, sem pendências. No CRF, empregador regular perante o FGTS.positiva_com_efeitos_de_negativa: há débitos suspensos ou garantidos. Vale como negativa.positiva: há pendências. No CRF, não existe certificado a emitir, e a validade vem vazia.nao_contribuinte: só na CND Federal, quando o CNPJ não está cadastrado na Receita.
validade_iso vem em AAAA-MM-DD, pronto para ordenar e filtrar. numero é o número da certidão ou do certificado, para conferir no site do órgão.
A coluna erro guarda só o que não adianta repetir: CNPJ_INVALIDO, quando o documento não tem o formato de um CNPJ. Esse caso chega em HTTP 200, sem exceção, e não é cobrado. Corrija o CNPJ em fornecedores.csv, apague a linha em certidoes.csv e rode de novo.
status: "erro" não entra na planilha. Ele quer dizer que o órgão não respondeu naquele momento ou recusou o pedido, e nas três certidões costuma ser passageiro. O script mostra a mensagem na tela, não cobra e consulta de novo na próxima rodada. Se a mensagem da CND Federal se repetir dizendo que o CNPJ é de filial, troque pelo CNPJ da matriz: a certidão sai para a matriz.
Quando consultar de novo
- CRF do FGTS: vale 30 dias. Quem acompanha fornecedor consulta todo mês.
- CND Federal e CNDT: valem 180 dias. Filtre
validade_isoe refaça as que vencem nas próximas semanas. - CND Federal: a API devolve a certidão que ainda vale; se ela não existe ou vence em até 3 dias, emite uma nova na mesma chamada, o que pode levar até cerca de 60 segundos.
- Renovar a CND Federal antes do vencimento: refazer a consulta devolve a mesma certidão enquanto ela valer por mais de 3 dias. Para sair com uma nova, de 180 dias, chame
api.consultar_cnd_federal(cnpj=cnpj, emitir_nova=True).
Para refazer só uma parte, apague as linhas dela em certidoes.csv e rode de novo.
Só a situação, numa chamada
Se você não precisa do PDF, /api/certidoes-todas consulta as três certidões em paralelo e conta como 1 consulta:
resp = api.consultar_certidoes_todas(cnpj="12345678000195", skip_estaduais=True)
for c in resp["certidoes_federais"]:
if c["result"]:
print(c["result"]["tipo"], c["result"]["status"], c["result"]["validade_iso"])Sem skip_estaduais, a mesma chamada inclui a CND estadual nos 27 estados e pode levar mais de um minuto. Detalhes em Consultar Todas as Certidões.
Quanto custa
| Plano | Uma certidão | As três, com PDF | Por minuto |
|---|---|---|---|
| Lite | R$ 0,67 | R$ 2,01 | 5 |
| Starter | R$ 0,10 | R$ 0,30 | 20 |
| Pro | R$ 0,065 | R$ 0,195 | 60 |
| Enterprise | R$ 0,025 | R$ 0,075 | 120 |
As três só com a situação, pela rota certidoes-todas, custam o mesmo que uma certidão. "Por minuto" é o número de consultas por minuto do plano.
Resposta com erro HTTP ou com status: "erro" não é cobrada. Veja Planos e limites e as comparações de APIs de CND Federal, CNDT e CRF do FGTS.
Perguntas frequentes
Existe API para tirar a CND Federal, a CNDT e o CRF do FGTS?
Sim. A FiscalAPI tem uma rota para cada certidão e uma que consulta as três de uma vez. Todas pedem só o CNPJ e devolvem a situação, a validade e o número em JSON; as rotas individuais trazem também o PDF.
Como automatizar as certidões de vários fornecedores?
Com uma lista de CNPJs e uma chamada por certidão. O script desta página grava a situação e a validade numa planilha e salva os PDFs numa pasta, e pode rodar todo mês.
Precisa de certificado digital ou procuração?
Não. As três certidões são emitidas só com o CNPJ.
Dá para consultar por CPF?
A CNDT e o CRF aceitam CPF. A CND Federal, por enquanto, só CNPJ.
A API devolve o PDF da certidão?
Sim, em base64, no campo pdf_base64 de cada rota individual. A rota que consulta as três de uma vez não traz os PDFs.
Esta pagina foi util?
Como consultar o Simples Nacional de uma lista de CNPJs?
Script pronto em Python: lê a planilha de CNPJs, consulta o Simples Nacional ao vivo e grava optante, data da opção, MEI e regime de IBS/CBS.
Como migrar do SintegrAPI ou do SintegraWS para a FiscalAPI?
Equivalência de endpoints, parâmetros, campos e erros entre o SintegrAPI, o SintegraWS e a FiscalAPI na consulta de inscrição estadual, com o que muda no código e o custo por consulta pelos preços públicos.