docs · base agosto/2026Atualizado em

GET /v1/cnpjs

Lista empresas por UF, município, CNAE, porte, situação cadastral, Simples, MEI, natureza jurídica, capital social e data de abertura. Paginação por cursor, cobrança por empresa retornada, perfil basic.

GET /v1/cnpjs lista empresas que atendem a um conjunto de filtros. Cada página traz até 20 empresas no perfil basic e custa 1 crédito por empresa retornada; página vazia custa 0. A paginação é por cursor opaco, com ordenação fixa por CNPJ. A busca exige um plano pago: no Free ela responde 403 insufficient_plan. Ela também exige ao menos um filtro além de cursor.

O que retorna

data é um array de empresas no perfil basic, os mesmos campos da consulta por CNPJ sem contatos e sócios. Para os contatos de uma empresa da lista, faça a consulta individual em full; os sinais has_phone, has_email e has_website já vêm na busca e dizem para quais vale a pena.

meta traz, além dos campos de toda resposta, três específicos da busca:

  • next_cursor: o cursor da página seguinte, ou null na última.
  • page_size: quantas empresas vieram nesta página. É campo de resposta; não existe parâmetro para pedir páginas maiores.
  • total_count_capped: texto com a contagem de empresas que atendem aos filtros. Abaixo do teto de exibição é exata; a partir dele vem com o sufixo + (por exemplo "10000+") e informa um mínimo. null quando não foi calculada. É uma contagem com teto, nunca uma estimativa.

Filtros

Os filtros se combinam com E lógico e ao menos um deles é obrigatório; sem filtro a resposta é 400 invalid_filter. Os parâmetros de código aceitam vários valores separados por vírgula (uf=SP,RJ, cnae=47,6201501): os valores de um mesmo parâmetro se combinam com OU, e municipio_excluir exclui todos os municípios da lista. O limite de valores por parâmetro está na referência gerada; acima dele a resposta é 400 invalid_filter. nome e socio_nome buscam texto contido, sem diferenciar maiúsculas. Não há ordenação escolhida pelo cliente: a ordem é sempre por CNPJ, o que torna a paginação estável.

Cada filtro tem um plano mínimo. Filtro acima do plano da conta responde 403 filter_not_in_plan, sem consulta e sem custo, e a mensagem diz qual plano libera o filtro.

Parâmetro Tipo Valores Plano mínimo
uf string Sigla da unidade federativa (PR, SP); aceita lista Starter
municipio string Código IBGE do município, sete dígitos (4106902 = Curitiba); aceita lista Starter
cnae string CNAE fiscal: subclasse de sete dígitos sem pontuação (1091102) ou um prefixo (classe, grupo ou divisão); aceita lista, com prefixos de tamanhos diferentes Starter
porte string ME, EPP ou DEMAIS; a correspondência com os códigos da Receita Federal está em Campos; aceita lista Starter
situacao string ATIVA, SUSPENSA, INAPTA, BAIXADA ou NULA; os códigos correspondentes estão em Campos; aceita lista Starter
simples boolean Optante do Simples Nacional Starter
mei boolean Optante do MEI Starter
natureza string Código da natureza jurídica, quatro dígitos; aceita lista Starter
capital_min, capital_max number Faixa de capital social em reais Starter
abertura_de, abertura_ate date Faixa de data de início de atividade, AAAA-MM-DD Starter
regime string LUCRO_PRESUMIDO, LUCRO_REAL, LUCRO_ARBITRADO, IMUNE ou ISENTA; casa também os regimes combinados que contêm o pedido; aceita lista Starter
cnae_secundario boolean Com true, cnae casa também os CNAEs secundários; exige cnae Starter
natureza_categoria string Primeiro dígito da natureza jurídica, de 1 a 5; aceita lista Starter
matriz_filial string MATRIZ ou FILIAL Starter
filiais_min, filiais_max integer Faixa de número de filiais Starter
situacao_data_de, situacao_data_ate date Faixa de data da situação cadastral, AAAA-MM-DD; empresas sem data da situação não entram Starter
motivo_situacao string Código do motivo da situação, dois dígitos; aceita lista Starter
situacao_especial string Código da situação especial, de 1 a 8; aceita lista Starter
municipio_excluir string Código IBGE do município a excluir, sete dígitos; aceita lista e exclui todos Starter
cep string Prefixo do CEP, de um a oito dígitos Starter
bairro string Nome do bairro, igual ao gravado Starter
com_email, com_site, com_telefone, com_celular boolean true exige o contato; false exige que ele não exista Starter
nome string Texto contido na razão social ou no nome fantasia, de 3 a 100 caracteres Starter
socio_nome string Texto contido no nome de algum sócio, de 3 a 100 caracteres Pro
socio_cnpj string CNPJ de sócio pessoa jurídica, com ou sem pontuação; CPF não é aceito Pro
socio_qualificacao string Código de qualificação do sócio, um ou dois dígitos; aceita lista Pro
cep_raio, raio_metros string, integer Empresas a até raio_metros (de 100 a 20000) do CEP de oito dígitos, no município do CEP; os dois vêm juntos Pro
faturamento string ATE_360MIL, DE_360MIL_A_4_8MI ou ACIMA_4_8MI: a mesma faixa de faturamento, derivada do porte, que a consulta full mostra; aceita lista Pro
funcionarios_min, funcionarios_max integer Faixa do número esperado de funcionários (modelo estatístico da Oportunidados, arredondado), o mesmo da faixa que a consulta full mostra; empresa sem distribuição válida não entra Pro
explicacao string Ignorado: existe para que a saída de POST /v1/filters/generate possa ser repassada inteira; não filtra e não conta como filtro —
cursor string Cursor opaco devolvido em meta.next_cursor da página anterior; os demais filtros não podem mudar —

Filtros de sócio respeitam os pedidos de remoção dos titulares: empresa com remoção ativa não aparece nessa busca nem na contagem.

Filtro desconhecido ou valor fora do enum responde 400 invalid_filter sem custo. Na busca, porte e situação são filtrados pelos nomes acima; na resposta, os mesmos campos vêm como código e descrição da Receita Federal, listados em Campos da resposta.

Exemplo de requisição

curl
# padarias ativas em Curitiba (CNAE 1091-1/02), optantes do Simples
curl "https://api.cnpj.ia.br/v1/cnpjs?uf=PR&municipio=4106902&cnae=1091102&situacao=ATIVA&simples=true" \
  -H "Authorization: Bearer $CNPJIA_KEY"

# próxima página
curl "https://api.cnpj.ia.br/v1/cnpjs?uf=PR&municipio=4106902&cnae=1091102&situacao=ATIVA&simples=true&cursor=<meta.next_cursor>" \
  -H "Authorization: Bearer $CNPJIA_KEY"
Python
import os, requests

HEADERS = {"Authorization": f"Bearer {os.environ['CNPJIA_KEY']}"}
filtros = {"uf": "PR", "municipio": "4106902", "cnae": "1091102", "situacao": "ATIVA", "simples": "true"}

def paginas(filtros: dict):
    cursor = None
    while True:
        params = {**filtros, **({"cursor": cursor} if cursor else {})}
        r = requests.get("https://api.cnpj.ia.br/v1/cnpjs", params=params, headers=HEADERS, timeout=10)
        r.raise_for_status()
        body = r.json()
        yield from body["data"]
        cursor = body["meta"].get("next_cursor")
        if not cursor:
            break

for empresa in paginas(filtros):
    print(empresa["cnpj"], empresa["razao_social"])
Node
const headers = { Authorization: `Bearer ${process.env.CNPJIA_KEY}` };
const filtros = { uf: "PR", municipio: "4106902", cnae: "1091102", situacao: "ATIVA", simples: "true" };

async function* paginas(filtros) {
  let cursor;
  do {
    const url = new URL("https://api.cnpj.ia.br/v1/cnpjs");
    Object.entries({ ...filtros, ...(cursor && { cursor }) }).forEach(([k, v]) => url.searchParams.set(k, v));
    const res = await fetch(url, { headers });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const { data, meta } = await res.json();
    yield* data;
    cursor = meta.next_cursor;
  } while (cursor);
}

for await (const e of paginas(filtros)) console.log(e.cnpj, e.razao_social);

Paginação e custo

Repita a chamada com os mesmos filtros, passando em cursor o valor de meta.next_cursor da página anterior, até ele vir null. Mudar um filtro no meio invalida o cursor. Cada página cobra 1 crédito por empresa retornada, então percorrer todas as empresas custa tantos créditos quantas empresas houver; total_count_capped na primeira página dá esse número quando está abaixo do teto, e um mínimo quando vem com +. Quando o saldo da conta não cobre uma página inteira, a página vem menor, com as empresas que o saldo paga, e next_cursor continua apontando para a seguinte.

Erros

Status Código Quando
400 invalid_filter Filtro desconhecido, valor fora da tabela, lista acima do limite, par incompleto (cep_raio sem raio_metros, cnae_secundario sem cnae), cursor inválido ou nenhum filtro além de cursor
401 invalid_api_key, key_expired Chave ausente, revogada ou vencida
402 quota_exceeded Franquia e pacotes esgotados
403 insufficient_plan, filter_not_in_plan, payment_required Plano sem busca (Free; o menor plano com busca é o Starter) ou busca ainda fechada na liberação gradual; filtro acima do plano da conta; cobrança em atraso
404 not_found API desligada
429 rate_limited Requisições por minuto da conta excedidas, ou limite por IP antes da autenticação
500 internal_error Falha não prevista; nada é cobrado. Hoje inclui o tempo limite da busca, que passará a responder 504
503 maintenance Janela de atualização da base
504 upstream_timeout Tempo limite na consulta; nada é cobrado

Relacionados

Perguntas frequentes

Posso buscar por nome da empresa?

Sim, pelo parâmetro nome: ele casa as empresas cuja razão social ou nome fantasia contém o texto, sem diferenciar maiúsculas, e se combina com os demais filtros (por exemplo uf e municipio). Para o nome de um sócio, use socio_nome. Com o CNPJ em mãos, a consulta individual é mais direta.

Por que a busca não vem no plano Free?

Porque uma única busca pode percorrer milhares de empresas e a franquia do Free é feita para testar a integração. A busca está em todos os planos pagos; no Free ela responde 403 insufficient_plan sem consumir crédito. Entre os planos pagos muda o conjunto de filtros: sócio, raio, faturamento e funcionários ficam nos planos acima do de entrada, e filtro acima do plano responde 403 filter_not_in_plan, também sem custo. A tabela de filtros mostra o plano mínimo de cada um.

Como sei quanto uma busca vai custar antes de rodar?

Pela primeira página: meta.total_count_capped traz quantas empresas atendem aos filtros, exato abaixo do teto de exibição e um mínimo quando vem com +, e a cobrança é por empresa retornada. Se o número passar do que você quer gastar, refine os filtros antes de paginar.

A ordem dos resultados muda entre páginas?

Não. A ordenação é fixa por CNPJ e a paginação usa cursor, então uma empresa não aparece duas vezes nem some entre páginas enquanto os filtros forem os mesmos. Mudar um filtro invalida o cursor.

A busca devolve telefone e e-mail?

Não. A busca devolve o perfil basic de cada empresa, com os sinais has_phone, has_email e has_website. Para os contatos, consulte a empresa em full; o sinal evita pagar o custo do full por uma empresa sem contato.