EvoDATA

Referência

API EvoDATA

Acesso em JSON ao cadastro público de CNPJ da Receita Federal: busca por 27 filtros combináveis, ficha completa com quadro societário e tabelas de referência.

Baixar OpenAPI 3.1

Começando

Todos os recursos vivem sob um único host, em uma versão fixada no caminho. Não há SDK: qualquer cliente HTTP serve.

URL basehttps://evodata.app/api/v1
ProtocoloHTTPS obrigatório. Chamadas em HTTP recebem redirecionamento permanente.
Formatoapplication/json, codificado em UTF-8. Acentos saem escapados como \uXXXX, que é JSON válido.
MétodosSomente GET. A API é de leitura.
Versãov1. Campos novos podem ser acrescentados sem aviso; remoções e mudanças de tipo abrem uma versão nova.

Primeira chamada

curl "https://evodata.app/api/v1/empresas?uf=DF&situacao=02&por_pagina=1"

Autenticação

Existem dois regimes, conforme a sensibilidade do dado:

RecursosAcesso
/empresas, /referencias Público. Nenhuma credencial. É cadastro aberto da Receita Federal.
/pessoas Chave obrigatória + plano pago. São dados pessoais.

Obtendo a chave

Emita em Chaves de API, no painel. A chave em claro aparece uma única vez, no momento da criação: o sistema guarda apenas um SHA-256, então nem o suporte consegue recuperá-la. Perdeu, revogue e emita outra. Cada conta pode manter até 5 chaves ativas — use uma por integração, para poder revogar uma sem derrubar as demais.

Enviando a chave

curl -H "Authorization: Bearer evd_SUA_CHAVE" \
  "https://evodata.app/api/v1/pessoas?nome=MARIA&uf=SP"

O cabeçalho X-API-Key é aceito como alternativa. A chave não é lida da query string, de propósito: parâmetro de URL vaza em log de servidor, histórico de navegador e cabeçalho Referer.

Quem tem direito. A API de pessoas exige conta de administrador ou plano Essencial, Profissional ou Corporativo. O plano gratuito recebe 403 plano_sem_api — a permissão é do plano, não do saldo de créditos, então zerar ou acumular créditos não muda nada. A busca pela interface web segue disponível a todos.

Recusas possíveis

HTTPerroSignificado
401credencial_ausenteNenhuma chave foi enviada.
401credencial_invalidaChave inexistente, revogada ou expirada. Os três casos respondem igual, para não confirmar que uma chave já existiu.
403plano_sem_apiChave válida, conta sem direito. Trocar a chave não resolve; mudar de plano sim.

Limites de uso

O custo real de cada chamada é uma consulta em um PostgreSQL de ~118 GB compartilhado com outro sistema em produção. O limite protege o banco, não o servidor de aplicação.

SituaçãoLimiteChave
Anônimo — recursos públicos20 req/minEndereço IP
Autenticado por chave120 req/minID da conta

Cabeçalhos em toda resposta

X-RateLimit-LimitTeto da janela corrente.
X-RateLimit-RemainingQuanto resta antes do bloqueio.
Retry-AfterSegundos até liberar. Presente apenas no 429.

Convenções

Listas

Parâmetros marcados como lista aceitam duas formas equivalentes. Valores repetidos são deduplicados e a ordem é irrelevante.

?uf=SP,RJ,MG          # separados por vírgula
?uf[]=SP&uf[]=RJ      # repetindo a chave

Valores fora do domínio

Filtros com domínio fechado — uf, situacao, porte, size_class, buscar_em, ordenar — descartam em silêncio o que não reconhecem, em vez de devolver erro. Uma UF digitada errado simplesmente não filtra. Se a lista inteira for inválida, o padrão do campo volta a valer.

Booleanos

Campos boolean ativam com 1, true, on ou yes; qualquer outra coisa desativa. Os campos marcados boolean³ são ternários: aceitam 1/true/S para sim, 0/false/N para não, e tratam a ausência como “indiferente”, que é diferente de “não”.

Números e datas

Valores monetários aceitam ponto ou vírgula decimal: 1500.50 e 1.500,50 chegam ao mesmo lugar. Datas usam AAAA-MM-DD e passam por validação de calendário — 2025-02-30 é descartada silenciosamente.

Buscar empresas

GET https://evodata.app/api/v1/empresas

Busca paginada sobre estabelecimentos. Ao menos um filtro é obrigatório — uma consulta irrestrita sobre dezenas de milhões de linhas não é atendida e devolve 422.

situacao tem padrão 02 (ativa) e não conta como filtro para essa exigência. Chamar /empresas?situacao=02 ainda resulta em filtros_ausentes.

Parâmetros

Identificação

ParâmetroTipoDescriçãoExemplo
q string Termo livre sobre razão social ou nome fantasia, conforme buscar_em. Se o valor contiver apenas dígitos (com ou sem pontuação de CNPJ) e tiver 8 ou mais deles, é reinterpretado como cnpj e o termo é descartado. padaria
buscar_em enum Onde q incide: razao, fantasia ou ambos. Valor desconhecido cai no padrão. ambos
cnpj string CNPJ completo ou raiz. Pontuação é ignorada. Tem precedência sobre q. 62.170.939/0001-51

Localização

ParâmetroTipoDescriçãoExemplo
uf lista Siglas de estado. Valores fora da tabela oficial são descartados em silêncio. SP,RJ
municipio lista Códigos de município da Receita — não o nome. Obtenha em /referencias/municipios/{uf}. 7107
bairro string Nome do bairro, casamento por prefixo. Centro
cep string Prefixo de CEP. Só dígitos são considerados. 01310

Atividade econômica

ParâmetroTipoDescriçãoExemplo
cnae lista Códigos CNAE de 7 dígitos. Busque o código em /referencias/cnae. 4721102
cnae_secundario boolean Quando verdadeiro, casa também no CNAE secundário do estabelecimento, não só no principal. 1
natureza lista Códigos de natureza jurídica. 2135

Situação e porte

ParâmetroTipoDescriçãoExemplo
situacao lista Códigos de situação cadastral. Padrão: 02 (ativa) — para incluir baixadas é preciso informar explicitamente. 02,08
matriz_filial enum 1 somente matrizes, 2 somente filiais. Ausente traz ambas. 1
porte lista Códigos de porte declarado. 01,03
abertura_de data Data de abertura mínima, em AAAA-MM-DD. Data inexistente no calendário é descartada. 2024-01-01
abertura_ate data Data de abertura máxima, em AAAA-MM-DD. 2025-12-31
capital_min número Capital social mínimo. Aceita 1500.50 e 1.500,50. 10000
capital_max número Capital social máximo. 5000000
mei boolean³ 1 só MEI, 0 exclui MEI, ausente é indiferente. 1
simples boolean³ 1 só optantes do Simples, 0 exclui, ausente é indiferente. 1

Presença de contato

ParâmetroTipoDescriçãoExemplo
com_email boolean Somente estabelecimentos com e-mail preenchido. 1
com_telefone boolean Somente com telefone preenchido. 1
com_celular boolean Somente com telefone identificado como celular. 1
com_geo boolean Somente com latitude e longitude resolvidas. 1

Enriquecimento

ParâmetroTipoDescriçãoExemplo
funcionarios_min inteiro Número mínimo estimado de funcionários. Vem de base de enriquecimento, não da Receita — nem todo estabelecimento tem. 10
funcionarios_max inteiro Número máximo estimado de funcionários. 500
size_class lista Classe de tamanho estimada: micro, pequena, media, grande. media,grande
rating_min número Avaliação mínima no Google Places, de 0 a 5. 4.0

Paginação e ordenação

ParâmetroTipoDescriçãoExemplo
ordenar enum Ordenação desejada. Pode ser recusada — veja Avisos. abertura_desc
pagina inteiro Página, começando em 1. Valores menores que 1 viram 1. 2
por_pagina inteiro Itens por página. Padrão 25, teto 100. 50

Resposta

{
  "dados": [ { /* objeto Empresa, ver abaixo */ } ],
  "paginacao": {
    "pagina": 1,
    "por_pagina": 25,
    "total": 482163,
    "total_exato": false,
    "tem_proxima": true
  },
  "avisos": []
}
total_exato: false muda o significado de total. Contar exatamente dezenas de milhões de linhas leva minutos, então acima de 5.000 resultados o número é a estimativa do planejador do PostgreSQL, não uma contagem. Trate-o como ordem de grandeza: não use para paginação exata nem para relatórios. Abaixo desse limiar a contagem é real e o campo vem true.

avisos é um array de strings. Hoje ele só recebe uma mensagem, quando a ordenação pedida em ordenar foi descartada: classificar um conjunto muito grande faz o planejador trocar o índice correto por uma varredura ordenada da tabela inteira. Nesse caso os resultados voltam na ordem natural do índice e a requisição segue sendo 200.

Objeto Empresa

CampoTipoDescrição
cnpj string 14 dígitos, sem pontuação.
cnpj_formatado string Com máscara: 00.000.000/0000-00.
razao_social string Razão social registrada.
nome_fantasia string|null Nome fantasia, quando declarado.
nome_exibicao string Fantasia quando existe, senão razão social. Pronto para exibir.
situacao string Rótulo legível: Ativa, Baixada, Suspensa, Inapta, Nula.
situacao_codigo string Código de dois dígitos correspondente.
ativa boolean Atalho para situacao_codigo === "02".
tipo_unidade string Matriz ou Filial.
cnae_codigo string CNAE principal, 7 dígitos.
cnae string Descrição do CNAE principal.
uf string Sigla do estado.
municipio string Nome do município.
bairro string|null Bairro.
cep string|null CEP com máscara.
endereco string Logradouro, número e complemento concatenados.
telefone string|null Telefone principal com DDD, formatado.
email string|null E-mail declarado à Receita.
porte string Porte declarado, legível.
natureza string Natureza jurídica, legível.
capital_social number Capital social em reais.
abertura string|null Data de abertura em AAAA-MM-DD.
funcionarios integer|null Estimativa de funcionários. Enriquecimento.
porte_estimado string|null Classe de tamanho estimada. Enriquecimento.
faturamento_estimado number|null Faturamento estimado. Enriquecimento.
confianca_estimativa string|null Confiança das estimativas acima. Enriquecimento.
latitude number|null Latitude. Google Places.
longitude number|null Longitude. Google Places.
avaliacao number|null Nota média, 0 a 5. Google Places.
avaliacoes_total integer|null Quantidade de avaliações. Google Places.
site string|null Site oficial. Google Places.
Campos marcados Enriquecimento ou Google Places não vêm da Receita Federal e existem apenas para parte da base. Espere null como caso comum, não como exceção.

Exemplo

curl -G "https://evodata.app/api/v1/empresas" \
  --data-urlencode "uf=SP,RJ" \
  --data-urlencode "cnae=4721102" \
  --data-urlencode "abertura_de=2024-01-01" \
  --data-urlencode "com_email=1" \
  --data-urlencode "ordenar=abertura_desc" \
  --data-urlencode "por_pagina=50"

Ficha de empresa

GET https://evodata.app/api/v1/empresas/{cnpj}

Retorna um único estabelecimento com todo o detalhamento. O CNPJ pode vir com ou sem máscara e é validado pelos dígitos verificadores antes de qualquer consulta — um CNPJ malformado devolve 422 sem tocar o banco.

curl "https://evodata.app/api/v1/empresas/62.170.939/0001-51"
curl "https://evodata.app/api/v1/empresas/62170939000151"   # equivalente

A resposta é { "dados": { … } } com todos os campos do objeto Empresa, mais os seguintes:

CampoTipoDescrição
cnpj_basico string Raiz de 8 dígitos, compartilhada por todas as unidades.
situacao_desde string|null Data da situação cadastral atual.
situacao_especial string|null Situação especial, quando houver.
telefone_secundario string|null Segundo telefone declarado.
cnaes_secundarios array Objetos {codigo, descricao} das atividades secundárias.
simples object|null Adesão ao Simples e ao MEI — ver abaixo.
socios array Quadro societário — ver abaixo.
unidades array Matriz e filiais que compartilham a raiz — ver abaixo.

Objeto sócio

{
  "nome": "FULANO DE TAL",
  "documento": "***040852**",        # PF sempre parcial
  "tipo": "Pessoa física",
  "eh_pessoa_juridica": false,
  "qualificacao": "Sócio-Administrador",
  "entrada": "2019-03-12",
  "faixa_etaria": "41 a 50 anos",
  "representante": null
}
O documento de sócio pessoa física vem parcial, no formato ***XXXXXX** — seis dígitos centrais, sem pontuação. É assim que a própria Receita Federal publica o quadro societário; o CPF completo não existe na origem e não há como recompô-lo. Sócio pessoa jurídica traz o CNPJ inteiro e formatado.

Objeto simples

{
  "optante": true,
  "desde": "2020-01-01",
  "excluido_em": null,
  "mei": true,
  "mei_desde": "2020-01-01",
  "mei_excluido_em": null
}

Objeto unidade

Lista com todas as unidades que compartilham a mesma raiz de CNPJ, incluindo a própria consultada. Útil para navegar de uma filial à matriz.

{
  "cnpj": "62170939000151",
  "cnpj_formatado": "62.170.939/0001-51",
  "nome_fantasia": null,
  "tipo": "Matriz",
  "eh_matriz": true,
  "situacao": "Ativa",
  "ativa": true,
  "uf": "DF",
  "municipio": "BRASILIA",
  "cnae": "Cabeleireiros, manicure e pedicure",
  "abertura": "2025-08-11"
}

Buscar pessoas

GET https://evodata.app/api/v1/pessoas chave + plano pago

Busca sobre 233 milhões de pessoas físicas. Ao menos um filtro é obrigatório. Diferente da busca de empresas, aqui não há paginação: o parâmetro por_pagina define quantas linhas voltam, e tem_mais indica se existem outras. Percorrer profundamente um conjunto de centenas de milhões de linhas não é uma operação que esta base sustente — o caminho é refinar até o recorte caber.

Parâmetros

ParâmetroTipoDescriçãoExemplo
nome string Início do nome. A base grava em maiúsculas e sem acento; a conversão é feita para você. MARIA DA SILVA
nome_mae string Início do nome da mãe. Combinado com nome, é o par mais eficaz para desambiguar homônimos. ANA
cpf string CPF completo, 11 dígitos. Pontuação ignorada. Parcial é recusado — ver abaixo. 000.000.001-91
rg string Número de RG, igualdade exata. 123456789
titulo_eleitor inteiro Título de eleitor completo. 123456789012
pis inteiro PIS/NIT completo. 12345678901
sexo enum M ou F. F
estado_civil enum S, C, D, V ou O. C
nasc_de data Nascimento mínimo, AAAA-MM-DD. 1980-01-01
nasc_ate data Nascimento máximo, AAAA-MM-DD. 1990-12-31
cbo string Código de ocupação, casa por prefixo. 2521
uf enum Estado de um endereço conhecido. SP
cidade string Cidade, por prefixo e sem acento. SAO PAULO
bairro string Bairro, por prefixo. CENTRO
logradouro string Nome do logradouro, sem “Rua” ou “Av.”. PAULISTA
cep string CEP completo, 8 dígitos. 01310-100
uf_emissao enum UF de emissão do RG. SP
email string E-mail completo ou o começo dele. Domínio sozinho é recusado — ver abaixo. joao.silva@
ddd inteiro DDD, de 11 a 99. 11
telefone inteiro Número completo, sem DDD e sem pontuação. 999998888
por_pagina inteiro Linhas retornadas. Padrão 25, teto 100. 50
Dois filtros são recusados de propósito, com 422 filtro_nao_suportado:

CPF parcial. A coluna é char(11) e um prefixo obrigaria varredura sobre 233 milhões de linhas. Informe os 11 dígitos.

Domínio de e-mail (@provedor.com). Nenhum índice cobre o final de uma string, e a coluna dominio da base guarda uma classificação (PUBLICO), não o domínio. Aceitar o filtro devolveria resultado plausível e errado.

Resposta

{
  "dados": [
    {
      "id": 2091705,
      "nome": "MARIA APARECIDA SILVA",
      "cpf": "***.456.789-**",
      "nome_mae": "ROSA MARIA BELLONI",
      "sexo": "F",
      "sexo_descricao": "Feminino",
      "nascimento": "1975-03-22",
      "idade": 51,
      "estado_civil": "C",
      "estado_civil_descricao": "Casado(a)",
      "cbo": "2521",
      "cidade": "SAO PAULO",
      "uf": "SP",
      "ddd": 11,
      "telefone": 999998888
    }
  ],
  "paginacao": {
    "por_pagina": 25,
    "retornados": 25,
    "tem_mais": true,
    "amostra": false
  },
  "consulta": {
    "condutor": "pessoas",
    "ms": 32
  }
}
amostra: true muda o significado do resultado. Quando o filtro mais seletivo ainda casa candidatos demais — uma UF sozinha, por exemplo —, a busca lê no máximo 4.000 candidatos e filtra dentro deles. O que volta é um recorte válido, mas não é “os primeiros N do conjunto” nem permite concluir que não existem outros. Para cobertura, refine até amostra vir false.

O bloco consulta é diagnóstico: condutor revela por qual tabela a consulta entrou, o que explica por que uma combinação ficou lenta. Filtros exatos — CPF, telefone, e-mail, CEP, PIS — conduzem por índice único e respondem em milissegundos; uf ou sexo sozinhos conduzem mal e tendem a virar amostra ou 503.

Exemplo

curl -H "Authorization: Bearer evd_SUA_CHAVE" -G "https://evodata.app/api/v1/pessoas" \
  --data-urlencode "nome=MARIA" \
  --data-urlencode "nome_mae=ANA" \
  --data-urlencode "uf=SP" \
  --data-urlencode "por_pagina=50"

Ficha de pessoa

GET https://evodata.app/api/v1/pessoas/{id} chave + plano pago

O id é o identificador interno devolvido no campo id da busca — não é o CPF, que nunca sai em claro por nenhum endpoint.

A resposta traz todos os campos da linha de busca, mais os blocos:

BlocoTipoConteúdo
obito_em string|null Data de óbito, quando registrada na origem.
nome_pai string|null Nome do pai.
rg string|null Número do RG, com orgao_emissor e uf_emissao.
nacionalidade string|null Nacionalidade declarada.
situacao_cadastral integer|null Código de situação, com situacao_cadastral_em.
documentos object pis, titulo_eleitor, zona, secao.
score object|null csb8 e csba com suas faixas de risco, de 0 a 1000.
perfil_financeiro object|null classe, codigo_classe e faixa de renda estimada.
enderecos array Até 12, do mais recente ao mais antigo.
telefones array Até 30, com tipo_descricao legível.
emails array Até 25, com qualidade e blacklist.
vinculos array Até 40 relações familiares, resolvidas nos dois sentidos do parentesco.
O CPF dos vínculos aparece em duas formas: ***.456.789-** quando a origem traz o documento da contraparte, e ***.***.***-** quando não traz. A tabela de parentesco grava apenas uma das direções, então a contraparte falta com frequência — trate a segunda forma como caso normal.

Tabelas de referência

Os filtros cnae e municipio esperam códigos. Estes dois endpoints resolvem nome para código e servem bem a campos de autocompletar.

Buscar CNAE

GET https://evodata.app/api/v1/referencias/cnae?q={termo}

Busca textual na descrição das atividades. Termos com menos de 2 caracteres devolvem lista vazia e 200 — não é erro.

curl "https://evodata.app/api/v1/referencias/cnae?q=padaria"

{
  "dados": [
    { "codigo": 1091102, "descricao": "Fabricação de produtos de padaria e confeitaria com predominância de produção própria" },
    { "codigo": 4721101, "descricao": "Padaria e confeitaria com predominância de produção própria" },
    { "codigo": 4721102, "descricao": "Padaria e confeitaria com predominância de revenda" }
  ]
}
codigo aqui volta como número, sem o zero à esquerda que alguns CNAEs têm. Ao repassar para o filtro cnae, trate como texto de 7 posições.

Municípios por UF

GET https://evodata.app/api/v1/referencias/municipios/{uf}

Todos os municípios de um estado, com o código que o filtro municipio espera. A sigla não diferencia maiúsculas.

curl "https://evodata.app/api/v1/referencias/municipios/df"

{ "dados": [ { "codigo": "9701", "nome": "BRASILIA" } ] }

Erros

Respostas de erro trazem erro, um código estável seguro para comparar em código, e quase sempre mensagem, texto em português voltado a quem lê — sujeito a mudar de redação. Compare pelo erro, nunca pela mensagem.

HTTPerroQuando acontece
422 filtros_ausentes GET /empresas sem nenhum filtro além do padrão de situação.
422 cnpj_invalido O CNPJ não passa na validação dos dígitos verificadores.
422 uf_invalida A sigla informada não está na tabela oficial.
404 nao_encontrado CNPJ válido, mas ausente da base da Receita.
429 Limite de requisições excedido. Corpo padrão do Laravel; veja os cabeçalhos.
503 consulta_expirada A combinação de filtros excedeu o tempo limite no banco.
{
  "erro": "filtros_ausentes",
  "mensagem": "Informe ao menos um filtro. A base tem 72 milhões de estabelecimentos e uma consulta irrestrita não é atendida."
}

O 503 consulta_expirada merece tratamento próprio: ele não indica indisponibilidade, e sim que aquela combinação de filtros é ampla demais para o tempo limite do banco. Repetir a mesma chamada tende a falhar de novo — o caminho é acrescentar um recorte mais estreito, como UF ou município. Vale notar que a consulta expirada não fica em cache: se o cache do PostgreSQL esquentar por outra via, a mesma chamada pode passar depois.

Enumerações

situacao

01Nula
02Ativa
03Suspensa
04Inapta
08Baixada

porte

00Não informado
01Microempresa
03Empresa de pequeno porte
05Demais

matriz_filial

1Matriz
2Filial

ordenar

relevanciaMais relevantes
abertura_descAbertura mais recente
abertura_ascAbertura mais antiga
capital_descMaior capital social
razao_ascRazão social (A–Z)

buscar_em

razaoRazão social (padrão)
fantasiaNome fantasia
ambosOs dois campos

size_class

microMicroempresa
pequenaPequeno porte
mediaMédio porte
grandeGrande porte

uf

AC AL AP AM BA CE DF ES GO MA MT MS MG PA PB PR PE PI RJ RN RS RO RR SC SP SE TO EX

EX designa estabelecimento sediado no exterior.

Limitações conhecidas

Nem tudo que a interface web faz está exposto por HTTP. Vale conhecer as fronteiras antes de desenhar a integração.

  • O CPF nunca sai em claro. Nenhum endpoint devolve o número completo — busca, ficha e vínculos trazem sempre a forma mascarada ***.XXX.XXX-**. A busca por CPF exige os 11 dígitos, de modo que a API confirme uma identidade que você já tem, em vez de permitir descobri-las.
  • Não há exportação em massa. O teto é 100 itens por página, e a paginação profunda fica cara porque o banco precisa descartar tudo que veio antes. Para volumes grandes, use a exportação da interface, que percorre o conjunto por chave e não repete nem omite registros.
  • Não há ordenação garantida. Qualquer valor de ordenar pode ser recusado em conjuntos grandes — a resposta continua 200, com a explicação em avisos. Um cliente que dependa de ordem precisa checar esse array.
  • Não há webhooks nem notificação de mudança. A base acompanha as publicações mensais da Receita Federal; descobrir o que mudou exige reconsultar.
  • Respostas são cacheadas. Buscas e fichas passam por cache de curta duração. Duas chamadas idênticas em sequência podem devolver exatamente o mesmo corpo mesmo que a base tenha mudado no meio.

Toda chamada é registrada na trilha de auditoria com origem, IP, alvo e volume de resultados, conforme descrito na política de privacidade.