API pública v1

Documentação da API

REST sobre HTTPS · autenticação por chave em header x-api-key · respostas JSON. Disponível a partir do plano Pro. Exemplos prontos pra colar em cURL, Node.js (fetch nativo) e Python (requests).

Filtros brasileiros nativos: a API foi pensada pra Receita Federal e CNPJ — /v1/public/search e /v1/public/aberturas aceitam filtros fiscais e cadastrais do Brasil (CNAE, UF, município, porte, situação cadastral, MEI/Simples Nacional, natureza jurídica, matriz/filial, abertura recente). Diferente de bases globais genéricas — sem precisar mapear country code ou converter NAICS pra CNAE.

1. Autenticação

Toda chamada à API pública exige header x-api-key: cnpj_live_…. Sem o header → HTTP 401.

Como criar a chave

  1. Logar em /login (magic-link) — exige plano Pro ou superior.
  2. Abrir /dashboard/api.
  3. Clicar em "Criar chave" e dar um nome descritivo (ex: "CRM produção").
  4. A chave plena aparece UMA única vez (formato cnpj_live_…). Copiar imediatamente pro gerenciador de senhas. Depois, só o prefixo (cnpj_live_t1G8…) fica visível — sem opção de re-revelar.
  5. Revogar: também em /dashboard/api. Revogação é instantânea — qualquer integração começa a retornar 401 imediatamente.
Pro tem até 2 chaves ativas · Enterprise até 10. Atingiu o cap? Revogue uma antes de criar outra.

2. Limites por plano

LimiteFreeStarterProEnterprise
Acesso à API públicaSimSim
Chaves ativas (max)210
Requisições/min (por chave)60300
Linhas/busca (cap por request)50200
Linhas/mês (export CSV/XLSX via UI)10010.000200.0005.000.000
Score em colunas do CSV/XLSXSimSim

Free e Starter usam só a UI (/buscar). API pública via x-api-key é Pro+. Ver planos.

3. Endpoints públicos

Base URL: https://cnpjplatform.com.br/api

Três endpoints públicos. Todos exigem x-api-key. Headers e formato de resposta são iguais — só o path muda.

GET/v1/public/cnpj/:cnpj

1. Buscar CNPJ por número

Retorna detalhe completo de uma empresa por CNPJ (14 dígitos, sem formatação). Inclui empresa + estabelecimento + lista de sócios + Lead Score (determinístico — calculado em SQL puro, sem IA).

Exemplos

cURL
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  https://cnpjplatform.com.br/api/v1/public/cnpj/33000167000101
Node.js
// Node 20+ (fetch nativo, sem deps)
const res = await fetch(
  'https://cnpjplatform.com.br/api/v1/public/cnpj/33000167000101',
  { headers: { 'x-api-key': process.env.CNPJ_API_KEY } },
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const empresa = await res.json();
console.log(empresa.empresa.razaoSocial);
// → "PETROLEO BRASILEIRO S A PETROBRAS"
Python
import os, requests

r = requests.get(
    "https://cnpjplatform.com.br/api/v1/public/cnpj/33000167000101",
    headers={"x-api-key": os.environ["CNPJ_API_KEY"]},
    timeout=10,
)
r.raise_for_status()
empresa = r.json()
print(empresa["empresa"]["razaoSocial"])
# → "PETROLEO BRASILEIRO S A PETROBRAS"

Resposta exemplo

{
  "cnpj": "33000167000101",
  "cnpjBasico": "33000167",
  "empresa": {
    "razaoSocial": "PETROLEO BRASILEIRO S A PETROBRAS",
    "naturezaJuridica": 2038,
    "naturezaJuridicaDesc": "Sociedade de Economia Mista",
    "capitalSocial": "205431960490.52",
    "porte": "05"
  },
  "estabelecimento": {
    "matriz": true,
    "nomeFantasia": "PETROBRAS - EDISE",
    "situacaoCadastral": 2,
    "situacaoCadastralDesc": "ATIVA",
    "dataInicioAtividade": "1966-09-28",
    "uf": "RJ",
    "municipio": "RIO DE JANEIRO",
    "cep": "20031912",
    "email": null,
    "telefone": "21 32242000"
  },
  "socios": [ /* … lista de sócios qualificação RF … */ ],
  "score": {
    "commercial": 92,
    "risk": 88,
    "segment": "Energia / Óleo & Gás",
    "persona": "Holding"
  }
}
404 se o CNPJ não existir na base atual da Receita Federal. Re-checar dia 14+ do mês (release nova). Sem fallback de enrichment externo.
GET/v1/public/search

2. Buscar empresas por filtros

Busca paginada com filtros combinados (CNAE, UF, capital, porte, situação, texto livre etc). Retorna lista resumida + total (estimado quando >10k matches). Mesmos filtros aceitos em /buscar via UI — a API é a versão programática.

Exemplos

cURL
# UF + porte
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  "https://cnpjplatform.com.br/api/v1/public/search?q=banco&uf=SP&porte=05&limit=20"

# Refinar por município (código da Receita Federal — 7107 = São Paulo,
# 6001 = Rio de Janeiro, 6291 = Campinas, 4123 = Belo Horizonte):
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  "https://cnpjplatform.com.br/api/v1/public/search?uf=SP&municipios=7107&porte=01&limit=20"

# Lookup nome → código RF (público, sem auth, audit 2026-05-10):
curl "https://cnpjplatform.com.br/api/v1/lookup/municipios?q=belo"
# → {"items":[{"codigoRf":4123,"nome":"BELO HORIZONTE","uf":null}, ...]}
Node.js
const params = new URLSearchParams({
  q: 'banco',
  uf: 'SP',
  // Município é array — append múltiplos códigos RF se quiser várias cidades
  municipios: '7107',  // São Paulo (código RF, NÃO IBGE)
  porte: '05',
  limit: '20',
});
const res = await fetch(
  `https://cnpjplatform.com.br/api/v1/public/search?${params}`,
  { headers: { 'x-api-key': process.env.CNPJ_API_KEY } },
);
const { items, total } = await res.json();
console.log(`${total} encontrados, mostrando ${items.length}`);
Python
r = requests.get(
    "https://cnpjplatform.com.br/api/v1/public/search",
    headers={"x-api-key": os.environ["CNPJ_API_KEY"]},
    # municipios aceita lista — códigos da Receita Federal (não IBGE)
    params={"q": "banco", "uf": "SP", "municipios": [7107], "porte": "05", "limit": 20},
    timeout=10,
)
data = r.json()
print(f"{data['total']} encontrados, mostrando {len(data['items'])}")

Resposta exemplo

{
  "total": 2857,
  "totalEstimated": true,
  "limit": 20,
  "offset": 0,
  "items": [
    {
      "cnpj": "00000000000191",
      "cnpjBasico": "00000000",
      "razaoSocial": "BANCO DO BRASIL SA",
      "nomeFantasia": "DIRECAO GERAL",
      "porte": "05",
      "capitalSocial": "120000000000.00",
      "uf": "DF",
      "municipio": "BRASILIA",
      "cnaePrincipal": 6422100,
      "score": {
        "commercial": 95,
        "risk": 96,
        "segment": "Bancos",
        "persona": "Holding"
      }
    },
    /* … mais 19 items … */
  ]
}
Filtros aceitos (combinar à vontade): q (texto livre), uf=SP,RJ, cnaeAny=4781400, cnaePrincipal=…, porte=01,03,05, capitalMin/Max, aberturaMin/Max, comEmail=true, comTelefone=true, apenasMei=true, apenasSimplesNacional=true.

Paginação: limit (1–50 no Pro, 1–200 no Enterprise) + offset. total vem como estimativa quando >10.000 matches (sinalizado por totalEstimated: true).
GET/v1/public/stats

3. Stats da base atual

Counts da base servida (empresas, estabelecimentos ativos, sócios) + release atual + timestamp. Útil pra exibir "última atualização" no seu dashboard ou validar que a base não ficou parada num mês.

Exemplos

cURL
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  https://cnpjplatform.com.br/api/v1/public/stats
Node.js
const res = await fetch('https://cnpjplatform.com.br/api/v1/public/stats', {
  headers: { 'x-api-key': process.env.CNPJ_API_KEY },
});
const stats = await res.json();
console.log(`Release ${stats.release}: ${stats.counts.empresas.toLocaleString('pt-BR')} empresas`);
Python
r = requests.get(
    "https://cnpjplatform.com.br/api/v1/public/stats",
    headers={"x-api-key": os.environ["CNPJ_API_KEY"]},
    timeout=5,
)
stats = r.json()
print(f"Release {stats['release']}: {stats['counts']['empresas']:,} empresas")

Resposta exemplo

{
  "counts": {
    "empresas": 67635192,
    "estabelecimentos": 70833888,
    "estabelecimentosAtivos": 28564948,
    "socios": 27495940,
    "cnaes": 1359
  },
  "release": "2026-04",
  "releaseFinishedAt": "2026-05-02T08:44:57-03",
  "fetchedAt": "2026-05-08T16:24:48.382Z"
}
Numbers vêm de pg_class.reltuples (estimativa do planner Postgres, refresh por autovacuum) — diferença típica vs count exato é < 1%, suficiente pra UI/dashboard. Cache Redis 1h.
POST/v1/public/enrich-batch

4. Enriquecer lista de CNPJs em massa (JSON)

Envie uma lista de até 100 CNPJs (Pro) ou 1.000 CNPJs (Enterprise) e receba dados enriquecidos em uma única request. Diferente do bulk upload via /dashboard/enriquecer (que processa CSV/XLSX assíncrono), este endpoint é síncrono e API-only. Throttle é por request (rate-limit do plano), não por linha. Free e Starter não têm acesso.

Exemplos

cURL
curl -X POST -H "x-api-key: cnpj_live_SUACHAVE" \
  -H "Content-Type: application/json" \
  https://cnpjplatform.com.br/api/v1/public/enrich-batch \
  -d '{"cnpjs": ["00000000000191", "33000167000101", "abc"]}'
Node.js
const res = await fetch('https://cnpjplatform.com.br/api/v1/public/enrich-batch', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.CNPJ_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    cnpjs: ['00000000000191', '33000167000101', 'abc'],
  }),
});
const { items, summary } = await res.json();
console.log(`Enriquecidas: ${summary.enriched} / Não encontradas: ${summary.not_found} / Inválidas: ${summary.invalid_cnpj}`);
Python
r = requests.post(
    "https://cnpjplatform.com.br/api/v1/public/enrich-batch",
    headers={"x-api-key": os.environ["CNPJ_API_KEY"]},
    json={"cnpjs": ["00000000000191", "33000167000101", "abc"]},
    timeout=15,
)
data = r.json()
for item in data["items"]:
    if item["status_lookup"] == "enriched":
        print(item["empresa"]["razao_social"], item["empresa"]["uf"])
    else:
        print(f"{item['input']}: {item['status_lookup']}")

Resposta exemplo

{
  "ok": true,
  "count": 3,
  "items": [
    {
      "input": "00000000000191",
      "cnpj": "00.000.000/0001-91",
      "status_lookup": "enriched",
      "empresa": {
        "razao_social": "BANCO DO BRASIL SA",
        "nome_fantasia": null,
        "uf": "DF",
        "municipio": "BRASILIA",
        "cnae_principal": 6422100,
        "porte": "05",
        "situacao": "ATIVA",
        "email": null,
        "telefone": "61 32932000",
        "capital_social": "120000000000.00",
        "data_inicio_atividade": "1966-08-01",
        "lead_score": {
          "commercial": 95,
          "risk": 96,
          "segment": "Bancos",
          "persona": "Holding"
        }
      }
    },
    {
      "input": "33000167000101",
      "cnpj": "33.000.167/0001-01",
      "status_lookup": "enriched",
      "empresa": { /* PETROLEO BRASILEIRO S A PETROBRAS … */ }
    },
    {
      "input": "abc",
      "status_lookup": "invalid_cnpj",
      "error_reason": "CNPJ inválido (formato ou DV)."
    }
  ],
  "summary": {
    "total": 3,
    "enriched": 2,
    "not_found": 0,
    "invalid_cnpj": 1
  },
  "tookMs": 142
}
Limites por plano: Pro 100 CNPJs/request · Enterprise 1.000 CNPJs/request. Acima disso devolve 413 too_many_cnpjs.

Status_lookup por item:
  • enriched — encontrado e enriquecido
  • not_found — CNPJ válido mas não está na base RF atual
  • invalid_cnpj — formato ou dígito verificador inválido (não derruba o request inteiro)

Cota e throttle: enrich-batch é metered por request rate (rate-limit do plano: Pro 60 req/min, Enterprise 300 req/min). NÃO consome cota mensal de bulk upload do dashboard. Pra grandes volumes recorrentes via dashboard, use /dashboard/enriquecer (CSV/XLSX async, com cota mensal de linhas).

Ordem da resposta: items[] preserva a ordem do input. Duplicatas no input recebem o mesmo enrichment (a query batched dedupe internamente, então não cobramos rate-limit extra por duplicatas — mas a ordem é mantida).

Privacidade: NÃO logamos a lista de CNPJs do seu request. Logs estruturados ficam em {keyId, plan, count, uniqueValid, okCount, notFoundCount, invalidCount} — sem conteúdo bruto.
GET/v1/public/aberturas

5. Empresas abertas recentemente

Atalho pra prospecção de leads novos: consulta empresas recém-abertas já presentes na base carregada da Receita Federal. Lista empresas ATIVAS com data_inicio_atividade nos últimos N dias, ordenadas mais recente primeiro. Equivale a /v1/public/search?aberturaMin=...&sortBy=data_inicio mas sem você ter que calcular a data. Free e Starter não têm acesso.

Não é monitoramento em tempo real, e não prometemos atualização diária: é uma fotografia da base no momento da release vigente da Receita Federal. Não tem email, não tem cron, não tem webhook, não tem alerta automático — pull, não push. Você consulta quando quiser; novos CNPJs entram na consulta quando uma release nova da RF é carregada.

Exemplos

cURL
# Últimos 30 dias, qualquer UF, primeiras 50:
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  "https://cnpjplatform.com.br/api/v1/public/aberturas?dias=30&limit=50"

# Últimos 7 dias em SP, CNAE 6201500 (desenv. de software):
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  "https://cnpjplatform.com.br/api/v1/public/aberturas?dias=7&uf=SP&cnae=6201500&limit=50"

# Últimos 30 dias na cidade de Campinas (código RF=6291, não IBGE):
curl -H "x-api-key: cnpj_live_SUACHAVE" \
  "https://cnpjplatform.com.br/api/v1/public/aberturas?dias=30&uf=SP&municipio=6291&limit=50"
Node.js
const params = new URLSearchParams({
  dias: '30',
  uf: 'SP',
  cnae: '6201500',  // desenvolvimento de software
  limit: '50',
});
const res = await fetch(
  `https://cnpjplatform.com.br/api/v1/public/aberturas?${params}`,
  { headers: { 'x-api-key': process.env.CNPJ_API_KEY } },
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { items } = await res.json();
for (const empresa of items) {
  console.log(empresa.data_inicio_atividade, empresa.razao_social, empresa.uf);
}
Python
r = requests.get(
    "https://cnpjplatform.com.br/api/v1/public/aberturas",
    params={"dias": 7, "uf": "SP", "cnae": 6201500, "limit": 50},
    headers={"x-api-key": os.environ["CNPJ_API_KEY"]},
    timeout=15,
)
r.raise_for_status()
for emp in r.json()["items"]:
    print(emp["data_inicio_atividade"], emp["razao_social"], emp["uf"])

Resposta exemplo

{
  "ok": true,
  "dias": 30,
  "limit": 50,
  "offset": 0,
  "items": [
    {
      "cnpj": "12.345.678/0001-90",
      "razao_social": "EXEMPLO SOFTWARE LTDA",
      "nome_fantasia": "Exemplo",
      "uf": "SP",
      "municipio": "SAO PAULO",
      "cnae_principal": 6201500,
      "porte": "01",
      "situacao": "ATIVA",
      "email": "contato@exemplo.com.br",
      "telefone": "11 999998888",
      "capital_social": "10000.00",
      "data_inicio_atividade": "2026-05-01",
      "matriz": true,
      "lead_score": {
        "commercial": 72,
        "risk": 65,
        "segment": "Tecnologia",
        "persona": "Pequena empresa"
      }
    }
    /* … até 50 itens (Pro) ou 200 (Enterprise) … */
  ],
  "tookMs": 38
}
Query params:
  • dias — janela em dias (default 30; max Pro 90, max Enterprise 365)
  • uf — UF de 2 letras (opcional; quando presente o planner usa o índice composto (uf, data_inicio_atividade DESC))
  • municipio — código da Receita Federal (4-5 dígitos; opcional). NÃO é o código IBGE — é o código RF próprio. Exemplos: 7107 = São Paulo, 6001 = Rio de Janeiro, 6291 = Campinas, 9701 = Brasília, 4123 = Belo Horizonte, 7535 = Curitiba.
  • cnae — CNAE principal 7 dígitos (opcional)
  • porte 01 (ME), 03 (EPP), 05 (Demais) ou 00 (não-informado) — opcional
  • limit — default 50; max Pro 50, max Enterprise 200
  • offset — default 0; max 10000 (paginação rasa)

Códigos de erro:
  • 400 validation_error — query mal-formada (ex: dias=abc, uf=AAA)
  • 403 plan_required — Free/Starter
  • 422 days_exceeded / limit_exceeded — acima do cap do seu plano

Sem total / sem COUNT(*): a base tem ~30M de empresas ativas; um COUNT(*) exato em filtros amplos (ex: dias=365 sem UF) custaria 5-10s e nem mudaria a decisão de UI. Pagine via offset até items.length < limit.

Não é alerta: este endpoint é pull, não push. Se você quer "novas aberturas no setor X todo dia", agende uma chamada cron no seu lado — a gente não dispara email, webhook ou notificação.

Privacidade: log estruturado tem só {keyId, plan, dias, hasUf, hasCnae, rows, tookMs} — sem queries cruas, sem CNPJs retornados.

4. Exportação CSV / XLSX

Exportação grande (até 1M linhas no Enterprise) acontece via UI em /buscar não via API pública. O fluxo é assíncrono (job na fila + polling) e os arquivos saem em CSV ou XLSX nativo.

CSV vs Excel (XLSX)

CSV (default)

  • • BOM UTF-8 + separador ;
  • • Compatível com qualquer ETL / CRM / Sheets
  • • Mais rápido pra ler programaticamente
  • • Datas como string ISO; CNPJ como texto formatado

Excel (XLSX)

  • • Abre direto no Excel / Google Sheets / LibreOffice
  • • Header em negrito + linha congelada
  • • CNPJ/CEP/CNAE preservam zeros à esquerda
  • • Capital social como número (não string)
  • • Datas formatadas dd/mm/yyyy

Como pedir o formato

A request POST de export aceita campo format:

POST /v1/exports
Content-Type: application/json

# CSV (default — compatibilidade com integrações antigas)
{
  "filters": { "uf": ["SP"], "porte": ["05"], "comEmail": true },
  "format": "csv",
  "maxRows": 5000
}

# XLSX nativo (abre direto no Excel/Google Sheets/LibreOffice)
{
  "filters": { "uf": ["SP"], "porte": ["05"], "comEmail": true },
  "format": "xlsx",
  "maxRows": 5000
}

Sem o campo format, o default é "csv" (compatibilidade com integrações antigas). Setar "format": "xlsx" gera um .xlsx nativo (Excel aceita sem conversão).

Score nas colunas: regra honesta

Score Comercial / Score de Risco / segment / persona aparecem como colunas extras no CSV E no XLSX APENAS no plano Pro e Enterprise. No Starter, o score aparece só na busca e na ordenação — o arquivo exportado (CSV ou XLSX) sai com as 14 colunas base, sem as 4 colunas de score.

Lead Score é determinístico — calculado em SQL puro sobre dados públicos da Receita Federal. Sem rede neural, sem LLM, sem caixa-preta. Detalhes: FAQ.

Limite por plano (export via UI)

  • Free: 100 linhas/mês · max 100 linhas/export · CSV ou XLSX (sem score)
  • Starter: 10.000 linhas/mês · max 5.000 linhas/export · CSV ou XLSX (sem score)
  • Pro: 200.000 linhas/mês · max 50.000 linhas/export · CSV ou XLSX (com score)
  • Enterprise: 5M linhas/mês · max 1M linhas/export · CSV ou XLSX (com score)

5. Bulk upload — enriquecer planilha CSV/XLSX

Subir um arquivo com sua lista de CNPJs e receber de volta o mesmo arquivo enriquecido com razão social, situação, CNAE, UF, município, capital social e — para Pro+ — Lead Score. Ideal para quem já tem uma base própria e quer cruzar com a Receita Federal sem buscar CNPJ por CNPJ.

Nesta versão, o upload de planilhas é feito pelo dashboard com usuário logado. A rota /v1/enrich exige sessão de cookie. NÃO aceita x-api-key nem Authorization Bearer — qualquer integração via API key recebe 401 unauthorised. Se você precisa enriquecer programaticamente em batch, abra o dashboard manualmente.

Disponibilidade por plano

  • Free: bulk upload NÃO incluso (rota retorna 402 plan_required com upgrade pra Starter).
  • Starter: 500 linhas/mês · 500 por job · arquivo até 10 MB.
  • Pro: 5.000 linhas/mês · 2.000 por job · arquivo até 10 MB · inclui colunas de Lead Score no output.
  • Enterprise: 20.000 linhas/mês · 5.000 por job · arquivo até 10 MB · inclui colunas de Lead Score.

Como subir

  1. Logar em /login (magic-link).
  2. Abrir /dashboard/enriquecer.
  3. Arrastar o arquivo CSV ou XLSX. A primeira linha precisa ter um header chamado cnpj (case-insensitive).
  4. O job processa em background. Você acompanha pelo status ("Na fila" → "Processando" → "Pronto") e baixa o resultado quando terminar.

Formatos

Entrada

  • .csv (UTF-8, separador ;, , ou \t)
  • .xlsx (Excel/Google Sheets/LibreOffice)
  • • Coluna cnpj obrigatória (autodetect cobre lista numérica simples)

Saída

  • • Mesmo formato do input (csv → csv, xlsx → xlsx)
  • • Colunas cadastrais: cnpj, razao_social, nome_fantasia, situacao, uf, municipio, cnae_principal, porte, capital_social
  • • Faturamento estimado REMOVIDO (2026-05-09): operador reprovou. Output NÃO traz mais colunas faturamento_estimado_*. Capital social cru (RF) é o único campo fiscal exposto.
  • • Pro+ adiciona: score_commercial, score_risk, segment, persona
  • • Sempre: status_lookup + error_reason

status_lookup por linha

O output marca cada linha com um dos três valores. Linhas inválidas não derrubam o job — você recebe o arquivo completo e revisa o que falhou.

  • enriched — CNPJ válido + encontrado na base RF; colunas preenchidas.
  • not_found — CNPJ válido (DV módulo-11 OK) mas não consta na base RF (pode ter sido baixado antes da última release; coluna error_reason traz o motivo).
  • invalid_cnpj — não passou no check de 14 dígitos ou DV; error_reason mostra o que veio no campo.

Cota mensal

Audit-pos-Bulk-Upload Fase B (2026-05-08): a cota é compartilhada entre exports e enriquecimento. O backend soma export_jobs.rows_written + enrich_jobs.ok_rows (apenas jobs status='done'), ambos do mês corrente, e compara com o cap do plano. Você vê o breakdown na tela de /dashboard/enriquecer.

  • Apenas enriched conta pra cota linhas not_found e invalid_cnpj NÃO bilham. Você só paga pelo lookup com sucesso.
  • Jobs failed/cancelled NÃO contam. Falha de worker não é cobrada.
  • Tombstones contam (anti-abuse). Apagar um job done não devolve cota — mesma lógica do export.

Segurança

  • Não aceita .xlsm (planilhas com macros) — bloqueado por segurança.
  • Magic-byte check — extensão renomeada não engana o detector (PDF/JPEG disfarçados de CSV são rejeitados).
  • Anti zip-bomb — XLSX com inflação > 100× do tamanho do upload é bloqueado.
  • Anti formula injection — qualquer célula que comece com =, +, -, @ recebe prefixo ' no output (Excel renderiza como texto).
  • CSV linha > 10 KB rejeitada (defesa DoS via linha gigante).
  • Arquivo de upload é descartado logo após o processamento. O arquivo enriquecido (output) expira em 7 dias e é removido automaticamente.
  • Download é por sessão — outro usuário tentar baixar seu arquivo via token recebe 404.

Onde abrir

/dashboard/enriquecer (logado, plano Starter ou superior). Dúvidas operacionais — formato esperado, o que fazer com not_found, como dividir arquivo grande em jobs menores — /faq.

Buscas salvas (atalho de filtros)

Buscas salvas são recurso do dashboard, não da API pública. A rota /v1/saved-searches exige sessão de cookie e NÃO aceita x-api-key nesta versão. Salve filtros que usa com frequência em /buscar clicando em "Salvar busca", e gerencie em /dashboard/buscas-salvas.

Não há alerta por email, cron ou scheduler. Saved searches só armazenam o snapshot dos filtros — você decide quando aplicar. Limite por plano: Free 1 · Starter 5 · Pro 20 · Enterprise 100.

6. Buscas salvas (dashboard)

Salvar combinações de filtros pra reaplicar depois. Recurso exclusivo do dashboard — não é endpoint da API pública nesta versão. A rota /v1/saved-searches exige sessão de cookie e NÃO aceita x-api-key nem Authorization Bearer.

Sem alerta por email, sem cron, sem scheduler, sem notificação automática. "Buscas salvas" guarda apenas o snapshot dos filtros — nada roda em background, nada chega no seu email. Quando você clica em Aplicar, abrimos /buscar com os filtros prontos.

Limites por plano

  • Free: 1 busca salva.
  • Starter: 5 buscas salvas.
  • Pro: 20 buscas salvas.
  • Enterprise: 100 buscas salvas.

Como usar

  1. Logar em /login.
  2. Abrir /buscar, montar combinação de filtros (UF, CNAE, capital, abertura, etc.).
  3. Clicar em "Salvar busca" ao lado de "Exportar". Dar um nome (1–80 caracteres) e confirmar.
  4. Gerenciar as buscas salvas em /dashboard/buscas-salvas — aplicar, renomear, apagar.

Endpoints (cookie-only)

Reusáveis pelo SPA do dashboard. NÃO aceitam x-api-key — qualquer chamada com API key recebe 401. Cliente curl/server-to-server via Bearer JWT também é rejeitado.

  • GET /v1/saved-searches — lista buscas ativas + cota do plano.
  • POST /v1/saved-searches — cria com { name, filters }.
  • PATCH /v1/saved-searches/:id — renomeia ou atualiza filters.
  • POST /v1/saved-searches/:id/touch — atualiza last_used_at (Aplicar).
  • DELETE /v1/saved-searches/:id — soft-delete (devolve slot).

O que NÃO está aqui

  • Sem alerta por email quando algo muda na base.
  • Sem cron / scheduler rodando suas buscas em background.
  • Sem notificação automática via WhatsApp / push / Slack.
  • Sem export agendado a partir de busca salva.

Se você precisa disso pra prospecção contínua, hoje a alternativa é: agendar um cron do seu lado que chame a API pública (/v1/public/search) com os mesmos filtros — assim você controla cadência, formato e onde mandar. Buscas salvas ficam pro fluxo manual no dashboard.

7. Erros comuns

StatusBodyO que fazer
401{"error":"unauthorised","message":"Missing x-api-key header."}Adicione header x-api-key
401{"error":"unauthorised","message":"Invalid API key."}Chave inválida ou revogada. Cria nova em /dashboard/api
403{"error":"plan_required","required_plan":"pro"}Upgrade pra Pro em /precos
429{"error":"rate_limited","retryAfterSec":12}Backoff exponencial; respeitar retryAfterSec
400{"error":"validation_error","issues":[…]}Param inválido (ex: limit=99999). Ver issues[]
404{"error":"not_found"}CNPJ não existe na release atual. Re-checar dia 14+ do mês
500{"error":"internal_error"}Retry após 30s. Persistindo, ver /faq

8. Collections (Postman / Insomnia)

Pra acelerar o setup local, baixe a collection Postman pronta — tem os 3 endpoints + variáveis configuradas ({{api_key}}, {{base_url}}):

Baixar Postman collection (.json)

Insomnia também importa collections Postman direto (File → Import → escolher o JSON). Não precisamos manter format próprio.

Documentação da API · CNPJ.Platform