para quem enriquece contas · base agosto/2026

API de CNPJ para enriquecer CRM

Complete contas B2B a partir do CNPJ: cadastro, situação, CNAE, porte e, quando disponíveis, contatos, site, sócios sem CPF e faixa de faturamento.

Um CRM com CNPJ na conta pode ter cadastro completo e, quando disponíveis, telefone, e-mail, site, sócios e faixa de faturamento, com uma ou duas chamadas por registro. O perfil basic (1 crédito) diz se a empresa está ativa e se há contato para buscar; o full (6 créditos) traz o contato. Cada registro sai com a data da base da Receita Federal, hoje agosto/2026.

O fluxo em três passos

  1. Peça o basic primeiro

    O perfil basic traz cadastro, situação, CNAE, porte e os sinais has_phone, has_email e has_website. Já dá para segmentar e descartar contas inativas.

    GET /v1/cnpjs/{cnpj}                → data.situacao_cadastral, data.porte, data.has_phone
  2. Peça o full só onde há contato

    Quando has_phone, has_email ou has_website vierem verdadeiros, a consulta full traz os contatos disponíveis, sócios e faixa de faturamento; com meta.suppressed verdadeiro, os contatos vêm omitidos. Se toda conta precisa de sócios ou faixa, peça o full sempre: o basic não tem sinal para eles.

    GET /v1/cnpjs/{cnpj}?profile=full   → data.telefones, data.email, data.faixa_faturamento
  3. Grave a data da base junto

    meta.data_as_of diz qual foto mensal respondeu. É o campo que decide quando reenriquecer.

    conta.enriquecido_em = meta.data_as_of

Código pronto

A lógica é a mesma em qualquer stack: basic para todos, full só onde há contato, e meta.suppressed testado antes de ler os contatos.

Python
import os, requests

S = requests.Session()
S.headers["Authorization"] = f"Bearer {os.environ['CNPJIA_KEY']}"
API = "https://api.cnpj.ia.br/v1/cnpjs/"

def enriquecer(cnpj: str) -> dict:
    r = S.get(API + cnpj, timeout=10)
    r.raise_for_status()  # erro vem no envelope Error, sem data
    basic = r.json()
    d = basic["data"]
    registro = {
        "razao_social": d["razao_social"],
        "situacao": d["situacao_cadastral"]["descricao"],
        "porte": d["porte"]["descricao"],
        "cnae": d["cnae_fiscal"]["descricao"],
        "base": basic["meta"]["data_as_of"],
    }
    if d["has_phone"] or d["has_email"] or d["has_website"]:
        r = S.get(API + cnpj, params={"profile": "full"}, timeout=10)
        r.raise_for_status()
        resp = r.json()
        full, meta = resp["data"], resp["meta"]
        if not meta.get("suppressed"):  # pedido de remoção ativo omite os contatos
            registro.update(
                telefones=[t["ddd"] + t["numero"] for t in full.get("telefones") or []],
                email=full.get("email"),
                site=full.get("site"),
            )
        fx = full.get("faixa_faturamento")
        registro["faixa_faturamento"] = fx["faixa"] if fx else None
        registro["suprimido"] = bool(meta.get("suppressed"))
    return registro
Node
const headers = { Authorization: `Bearer ${process.env.CNPJIA_KEY}` };
const API = "https://api.cnpj.ia.br/v1/cnpjs/";

async function enriquecer(cnpj) {
  const r1 = await fetch(API + cnpj, { headers });
  if (!r1.ok) throw new Error(`cnpj.ia.br ${r1.status}`); // erro vem no envelope Error, sem data
  const basic = await r1.json();
  const d = basic.data;
  const registro = {
    razaoSocial: d.razao_social,
    situacao: d.situacao_cadastral.descricao,
    porte: d.porte.descricao,
    cnae: d.cnae_fiscal.descricao,
    base: basic.meta.data_as_of,
  };
  if (d.has_phone || d.has_email || d.has_website) {
    const r2 = await fetch(`${API}${cnpj}?profile=full`, { headers });
    if (!r2.ok) throw new Error(`cnpj.ia.br ${r2.status}`);
    const { data: full, meta } = await r2.json();
    if (!meta.suppressed) { // pedido de remoção ativo omite os contatos
      Object.assign(registro, {
        telefones: (full.telefones ?? []).map((t) => t.ddd + t.numero),
        email: full.email ?? null,
        site: full.site ?? null,
      });
    }
    registro.faixaFaturamento = full.faixa_faturamento?.faixa ?? null;
    registro.suprimido = Boolean(meta.suppressed);
  }
  return registro;
}

Campos mais usados

CampoPerfilDescrição
razao_socialbasicNome empresarial registrado na Receita Federal. É o único nome sempre presente.
nome_fantasiabasicNome fantasia declarado para o estabelecimento, na Receita Federal. null quando a empresa não declarou.
situacao_cadastral.descricaobasicDescrição da situação cadastral, traduzida do código pela tabela de domínio da Receita Federal.
porte.descricaobasicDescrição do porte, traduzida do código pela tabela de domínio da Receita Federal.
cnae_fiscal.descricaobasicNome da atividade econômica principal, traduzido do código pela tabela de CNAEs da Receita Federal.
telefones[].numerofullNúmero do telefone, sem DDD e sem pontuação, cadastrado na Receita Federal.
emailfullEndereço de correio eletrônico do contribuinte, campo da Receita Federal. null quando a empresa não tem e-mail na base.
sitefullSite institucional da empresa. Enriquecimento da Oportunidados (a Receita Federal não publica site): escolha determinística de uma URL institucional, pela confiança da fonte e depois pela coleta mais recente.
socios[].nomefullNome do sócio pessoa física, ou razão social do sócio pessoa jurídica, como publicado pela Receita Federal. Nunca acompanhado de CPF ou CNPJ do sócio.
faixa_faturamento.faixafullFaixa de faturamento DERIVADA do porte declarado à Receita Federal, em texto. Não é estimativa própria, não é valor apurado e não é faturamento observado.
faixa_funcionariosfullNúmero de funcionários em texto: pode ser um número exato ou um intervalo (por exemplo Entre 12 e 40). Enriquecimento da Oportunidados; null quando não há dado oficial.
meta.data_as_ofmetaData da base servida na resposta. A base é atualizada mensalmente; este campo está em toda resposta porque a consulta responde pela foto do mês, não pelo instante da chamada.

faixa_faturamento é derivada do porte declarado à Receita Federal e carrega origem: "porte". Não é estimativa nem valor apurado; trate como segmento, não como número. faixa_funcionarios é texto e pode vir null.

O que a resposta não traz

O uso dos contatos para abordagem comercial B2B e o que é proibido estão em Privacidade e uso aceitável.

Tier indicado

Free é o plano indicado: este fluxo não usa a busca de empresas.

  • 60 créditos por mês
  • 3 requisições por minuto

Todos os planos, os pesos por operação e os pacotes avulsos

Perguntas frequentes

Toda empresa tem telefone e e-mail na resposta?

Não. Vêm quando constam na base, no perfil full. O perfil basic traz os sinais has_phone, has_email e has_website, que dizem antes se vale pedir o full para aquela conta.

A faixa de faturamento serve para qualificar a conta?

Serve como segmento. Ela é derivada do porte que a empresa declarou à Receita Federal e o próprio campo diz isso em origem: "porte". Não é um valor apurado nem uma estimativa da Oportunidados.

Vem o CPF dos sócios?

Não, em nenhum perfil. O quadro societário traz nome, qualificação, data de entrada, país e faixa etária de cada sócio, e nome e qualificação do representante legal quando houver.

Com que frequência devo reenriquecer?

A base é uma foto mensal da Receita Federal. Grave meta.data_as_of em cada registro e reenriqueça quando GET /v1/status mostrar uma data nova; antes disso a resposta seria a mesma.

Posso usar os contatos para prospecção pelo CRM?

Para abordagem comercial a empresas, com contato do estabelecimento e respeito às regras do canal, sim. Mensagens em massa não solicitadas, revenda da base e tentativa de identificar pessoas físicas são proibidas. A API honra pedidos de remoção de contatos.

Quanto custa enriquecer uma base de contas?

Depende de quantas contas têm contato. O padrão é basic para todas e full só onde has_phone ou has_email vierem verdadeiros; os pesos estão em /precos, junto com a calculadora por volume mensal.

Para continuar

Criar chave grátis

Atualizado em