Consulta de CNPJ em Lote
Envie uma lista de até 10.000 CNPJs e receba, para cada um, o mesmo registro da Consulta de CNPJ, processado em segundo plano. Custa 1 crédito por CNPJ encontrado.
Usando Cursor, Lovable, v0 ou outra IA? Copie o prompt da consulta de CNPJ em lote e cole no seu assistente.
Sem código, o dashboard aceita uma lista de CNPJs e mostra o resultado de cada um.
Fluxo em dois passos:
POST /cnpj/bulkenvia a lista e responde na hora com umjobId.GET /cnpj/bulk/{jobId}devolve o progresso e os resultados. Repita atéstatusser"done"ou"failed".
Endpoint
https:/ / api.cpfhub.io/ cnpj/ bulkParâmetros
| Onde | Nome | Obrigatório | Descrição |
|---|---|---|---|
| Header | x-api-key | Sim | Sua API Key. Veja Autenticação. |
| Header | Content-Type | Sim | application/json |
| Body | cnpjs | Sim | string[] de CNPJs, com ou sem formatação, numéricos ou alfanuméricos. Não vazio, máximo 10.000. Itens que não são string contam como inválidos. |
| Body | fileName | Não | Rótulo livre. Volta como file_name no status. |
| Body | format | Não | Rótulo livre do formato de origem (ex.: "csv"). Volta como format. |
O que acontece no envio
| Etapa | Efeito |
|---|---|
| Normalização | Remove pontos, barra e traço e converte letras para maiúsculas. CNPJs com formato errado ou dígito verificador incorreto vão para invalid e não são cobrados. |
| Duplicados | Removidos. Cada CNPJ é consultado e cobrado uma vez. Não entram em totalRecords nem em invalid. |
| Saldo | Sem overage: o saldo precisa cobrir todos os CNPJs válidos (totalRecords × custo da consulta, 1 crédito no padrão). Se não cobrir, 403 e nada é cobrado. |
| Lotes pendentes | Existe um limite de lotes em processamento ao mesmo tempo por cliente. Acima dele, 429. |
Mais de 10.000 CNPJs: divida em blocos e envie um POST para cada um, aguardando os anteriores se receber 429.
Exemplo
Confira o status antes de ler data: em erro, a resposta não traz jobId.
curl -X POST "https://api.cpfhub.io/cnpj/bulk" \
-H "x-api-key: $CPFHUB_API_KEY" \
-H "content-type: application/json" \
-d '{
"cnpjs": ["11222333000181", "12.ABC.345/01DE-35"]
}'Resposta
HTTP 202 Accepted
{
"success": true,
"data": {
"jobId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "processing",
"totalRecords": 2,
"invalid": 0
}
}| Campo | Tipo | Descrição |
|---|---|---|
data.jobId | string | ID do lote. Guarde para consultar o status. |
data.status | string | Sempre "processing" |
data.totalRecords | number | CNPJs válidos e únicos que serão consultados |
data.invalid | number | Itens descartados (formato, dígito verificador ou não string) |
O envio responde em camelCase. O status responde em snake_case.
Status e resultados
https:/ / api.cpfhub.io/ cnpj/ bulk/ {jobId}Use a mesma API Key do envio. Não consome crédito e funciona com saldo zerado.
Polling:
- Comece a cada 5 s e aumente até 30 s em lotes grandes. Cada chamada devolve o array
cnpjsinteiro, e cada registro de CNPJ é bem maior que o de um CPF. - Defina um prazo máximo no cliente (ex.: 30 min). O tempo do lote depende de quantos CNPJs estão no envio.
- Em
5xxou erro de rede, tente de novo no próximo ciclo. OGETé seguro para repetir.
curl "https://api.cpfhub.io/cnpj/bulk/7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-H "x-api-key: $CPFHUB_API_KEY"HTTP 200 OK
{
"success": true,
"data": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "done",
"file_name": null,
"format": null,
"total_records": 2,
"processed": 2,
"found": 1,
"not_found": 1,
"skipped": 0,
"error": null,
"created_at": "2026-10-15T14:15:16.000Z",
"updated_at": "2026-10-15T14:15:18.000Z",
"cnpjs": [
{
"cnpj": "11222333000181",
"found": true,
"data": {
"cnpj": "11222333000181",
"razao_social": "EMPRESA EXEMPLO LTDA",
"situacao_cadastral": "Ativa",
"...": "demais campos da Consulta de CNPJ"
}
},
{
"cnpj": "12ABC34501DE35",
"found": false,
"data": null
}
]
}
}| Campo | Descrição |
|---|---|
data.id | ID do lote (o jobId do envio) |
data.status | "processing", "done" ou "failed" |
data.total_records | CNPJs válidos e únicos no lote |
data.processed | CNPJs já processados (inclui skipped) |
data.found | Encontrados. Cada um consome 1 crédito no padrão (custo do seu plano no dashboard) |
data.not_found | Não encontrados. Não consomem crédito. |
data.skipped | Não consultados porque o saldo acabou durante o lote (sem overage). Não consomem crédito. |
data.error | Motivo da falha quando status é "failed" |
data.file_name, data.format | Rótulos enviados no POST |
data.created_at, data.updated_at | Datas ISO 8601 |
data.cnpjs[] | Resultado de cada CNPJ processado: cnpj (14 caracteres sem máscara), found e data, que é o mesmo registro da Consulta de CNPJ ou null quando found é false |
Durante "processing", os contadores atualizam em intervalos e podem ficar atrás de cnpjs.
Erros
| Status | Quando acontece | O que fazer |
|---|---|---|
400 | cnpjs ausente, vazio, não é array ("Campo 'cnpjs' deve ser um array não vazio.") ou tem mais de 10.000 itens ("Limite de 10000 CNPJs por lote excedido.") | Corrija o body. |
401 | API Key ausente, inválida ou inativa (error string) | Confira o header x-api-key. |
403 | Sem overage: saldo menor que o lote (error.message: "Créditos insuficientes para o lote: N necessários."). Também saldo zerado e conta inativa/bloqueada. Só no POST. | Recarregue créditos ou reduza o lote. |
404 | jobId não existe ou foi criado com outra API Key ("Lote não encontrado.") | Confira o jobId e a chave. |
422 | Nenhum CNPJ válido na lista ("Nenhum CNPJ válido na lista enviada.") | Corrija a lista. |
429 | Limite por minuto excedido, ou limite de lotes pendentes ("Limite de N lotes pendentes por cliente excedido."). Só no POST. | Espere os segundos do header Retry-After (60 s no limite de lotes pendentes). Deixe os lotes anteriores terminarem antes de enviar outros. |
500 | "Falha ao criar lote." Nenhum lote foi criado. | Tente de novo. Reporte se persistir. |
Formato do erro e retentativas: Códigos de Erro. Limite por minuto e créditos: Limites de Uso.
Detalhes
Estados do lote
| Situação | Como identificar | O que fazer |
|---|---|---|
| Em processamento | status: "processing" | Continue o polling. cnpjs já traz resultados parciais. |
| Concluído | "done" e skipped: 0 | Use cnpjs. |
| Concluído com pulados | "done" e skipped > 0 | Saldo acabou durante o lote. Recarregue e reenvie só os CNPJs que faltaram. |
| Falhou | "failed" | Leia error. Os encontrados em cnpjs já foram cobrados. Reenvie só os que faltaram. |
Com overage, nenhum CNPJ é pulado: todos são consultados e o excedente é cobrado.
Casando os resultados com a sua lista
cnpjs não segue a ordem do envio e não inclui skipped nem não processados. Normalize sua lista (sem pontos, barra e traço, em maiúsculas) e case pelo campo cnpj. Os que faltarem são os que reenviar (inclui inválidos, que não custam nada).
const normalize = (cnpj: string) => cnpj.replace(/[./-]/g, '').toUpperCase()
const results = new Map(job.cnpjs.map((item) => [item.cnpj, item]))
for (const original of myCnpjs) {
const result = results.get(normalize(original))
console.log(original, result ? (result.found ? result.data.razao_social : 'não encontrado') : 'sem resultado')
}
// CNPJs para reenviar em um novo lote (se o lote falhou ou teve skipped)
const missing = [...new Set(myCnpjs.map(normalize))].filter((cnpj) => !results.has(cnpj))Mais
- Envio não idempotente: cada
POSTaceito cria um lote novo e cobra os encontrados. Se a conexão cair semjobId, confira o dashboard ouGET /quotaantes de reenviar. Com resposta de erro, nenhum lote foi criado. - Crédito: só
found: trueé cobrado, no mesmo custo e na mesma franquia da Consulta Simples de CPF. Inválidos, repetidos, não encontrados eskippednão. - Fonte dos dados: a mesma da Consulta de CNPJ: base pública mensal da Receita Federal, tratada pelo OpenCNPJ. Os dados podem estar defasados até a próxima atualização mensal.
- Dados de exemplo: os CNPJs e os dados acima são fictícios.
Atualizado em 15 de outubro de 2026