Documentação da API de CNPJ
Referência completa da API do apipj. Base: https://apipj.com.br/v1. Todas as respostas são JSON em UTF-8. Esta página também existe em Markdown e há um OpenAPI 3.1 gerado a partir das rotas. Para testar sem escrever código, abra o sandbox.
Visão geral
- Fonte dos dados: arquivos de dados abertos da Receita Federal do Brasil, carregados em lote uma vez por mês. Cada documento traz o campo
atualizado_emcom o mês do lote (AAAA-MM). Não há consulta em tempo real. - Autenticação: obrigatória em
GET /v1/cnpj(chave de API; sem chave a resposta é 401unauthorized). A conta é grátis e não pede cartão: 10 por minuto e 50.000 por mês./v1/validae/v1/statussão abertos. - Formatos:
completo(padrão: objetos aninhados, datas ISOAAAA-MM-DDe códigos da Receita ao lado das descrições) esimplificado(formato plano com campos já formatados: datas DD/MM/AAAA, CNPJ e CEP com pontuação), para integrações que preferem receber os valores prontos para exibir. - CNPJ alfanumérico: aceito em todos os endpoints desde o primeiro dia. Entrada com ou sem pontuação, maiúsculas ou minúsculas.
- CORS: liberado para
GET /v1/cnpj/*,/v1/valida/*e/v1/status; você pode chamar direto do navegador. - Compressão: gzip e brotli, negociadas pelo header
Accept-Encoding.
Autenticação
Crie uma conta em /criar-conta: a primeira chave é gerada na hora e exibida uma única vez. Você pode ter até 5 chaves ativas por conta e revogar qualquer uma no painel; a revogação é imediata.
Envie a chave de uma destas formas, em ordem de preferência:
| Forma | Exemplo | Observação |
|---|---|---|
Header Authorization | Authorization: Bearer apipj_live_... | Recomendado |
Header X-API-Key | X-API-Key: apipj_live_... | Alternativa para clientes que não montam Authorization |
Query string ?token= | /v1/cnpj/...?token=apipj_live_... | Só para clientes que não conseguem enviar cabeçalhos. Não recomendado: a chave vai parar em logs e históricos |
No próprio site (sandbox e consulta da página inicial), quem está logado consulta pela sessão (cookie, mesma origem), sem chave; o uso conta na mesma cota mensal da conta. Sem chave e sem sessão, GET /v1/cnpj responde 401 com {"status":"ERROR","message":"Crie uma conta grátis para consultar","code":"unauthorized"}.
Chaves têm o prefixo apipj_live_. Guardamos apenas um hash; se você perder a chave, revogue e crie outra. Nunca exponha a chave em código público, em apps distribuídos ou no front-end de sites abertos: use um backend intermediário.
Limites e cotas
Dois limites agem ao mesmo tempo: um por minuto (token bucket; zera a cada 60 segundos) e uma cota mensal por conta (somando todas as chaves e o uso pela sessão do site). Os valores vêm de /precos:
| Plano | Por minuto | Cota |
|---|---|---|
| Gratuito | 10 | 50.000 por mês |
| Dev (R$ 12,90) | 30 | 200.000 por mês |
| Pro (R$ 59,90) | 200 | 600.000 por mês |
Toda resposta de /v1/cnpj traz os cabeçalhos abaixo, inclusive em erro:
| Cabeçalho | Significado |
|---|---|
X-RateLimit-Limit | Consultas permitidas por minuto (por chave; no site, por conta) |
X-RateLimit-Remaining | Quantas ainda cabem neste minuto |
X-RateLimit-Reset | Segundos até o limite por minuto zerar |
X-Quota-Limit | Cota mensal da conta |
X-Quota-Remaining | Quanto resta da cota |
X-Quota-Reset | Segundos até a cota zerar |
Retry-After | Só em 429: segundos a esperar antes de tentar de novo |
A cota mensal reinicia no primeiro dia de cada mês (horário de Brasília) e não acumula. /v1/valida e /v1/status não consomem cota.
GET /v1/cnpj/{cnpj}
Devolve o documento cadastral de um CNPJ. Parâmetro de query formato: completo (padrão, pode ser omitido) ou simplificado. Qualquer outro valor responde 400 validation_error.
curl -s "https://apipj.com.br/v1/cnpj/11378117000120" \
-H "Accept: application/json" \
-H "Authorization: Bearer apipj_live_SUA_CHAVE"const resp = await fetch("https://apipj.com.br/v1/cnpj/11378117000120", {
headers: {
Accept: "application/json",
Authorization: "Bearer apipj_live_SUA_CHAVE",
},
});
if (!resp.ok) {
const erro = await resp.json().catch(() => ({}));
throw new Error(`HTTP ${resp.status}: ${erro.message ?? "erro"}`);
}
const dados = await resp.json();
console.log(dados.razao_social, dados.situacao_cadastral.descricao);
console.log("restam no minuto:", resp.headers.get("X-RateLimit-Remaining"));import requests
r = requests.get(
"https://apipj.com.br/v1/cnpj/11378117000120",
headers={
"Accept": "application/json",
"Authorization": "Bearer apipj_live_SUA_CHAVE",
},
timeout=10,
)
if r.status_code == 429:
raise SystemExit(f"limite: tente em {r.headers.get('Retry-After')} s")
r.raise_for_status()
dados = r.json()
print(dados["razao_social"], dados["situacao_cadastral"]["descricao"])<?php
$ch = curl_init("https://apipj.com.br/v1/cnpj/11378117000120");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Authorization: Bearer apipj_live_SUA_CHAVE",
],
]);
$corpo = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("HTTP $status: $corpo");
}
$dados = json_decode($corpo, true, 512, JSON_THROW_ON_ERROR);
echo $dados["razao_social"], " - ", $dados["situacao_cadastral"]["descricao"], PHP_EOL;using System.Net.Http.Headers;
using System.Text.Json;
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "apipj_live_SUA_CHAVE");
using var resp = await http.GetAsync("https://apipj.com.br/v1/cnpj/11378117000120");
if (!resp.IsSuccessStatusCode)
throw new HttpRequestException($"HTTP {(int)resp.StatusCode}: {await resp.Content.ReadAsStringAsync()}");
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var raiz = doc.RootElement;
Console.WriteLine(raiz.GetProperty("razao_social"));Resposta 200 (formato completo)
{
"cnpj": "11378117000120",
"cnpj_formatado": "11.378.117/0001-20",
"razao_social": "LEADS2B S/A",
"nome_fantasia": "LEADS2B.COM",
"matriz_filial": "MATRIZ",
"situacao_cadastral": {
"codigo": "02",
"descricao": "ATIVA",
"data": "2009-11-24",
"motivo": {
"codigo": "00",
"descricao": "SEM MOTIVO"
}
},
"situacao_especial": {
"descricao": null,
"data": null
},
"data_inicio_atividade": "2009-11-24",
"natureza_juridica": {
"codigo": "2054",
"descricao": "Sociedade Anônima Fechada"
},
"porte": {
"codigo": "05",
"descricao": "DEMAIS"
},
"capital_social": 218878,
"cnae_principal": {
"codigo": "6311900",
"descricao": "Tratamento de dados, provedores de serviços de aplicação e serviços de hospedagem na internet"
},
"cnaes_secundarios": [
{
"codigo": "8599604",
"descricao": "Treinamento em desenvolvimento profissional e gerencial"
}
],
"endereco": {
"tipo_logradouro": "RUA",
"logradouro": "PADRE ANCHIETA",
"numero": "2285",
"complemento": "CONJ 1603 ANDAR 16 COND BUSINESS CENTER",
"bairro": "BIGORRILHO",
"cep": "80730001",
"municipio": {
"codigo_ibge": "4106902",
"nome": "CURITIBA"
},
"uf": "PR",
"pais": null
},
"telefones": [
{
"ddd": "41",
"numero": "30287828"
}
],
"fax": null,
"email": "contabilidade@leads2b.com",
"ente_federativo_responsavel": null,
"simples": {
"optante": false,
"data_opcao": "2009-11-24",
"data_exclusao": "2019-12-31"
},
"mei": {
"optante": false,
"data_opcao": null,
"data_exclusao": null
},
"socios": [
{
"nome": "FULANO DE TAL",
"tipo": "PESSOA FISICA",
"cpf_cnpj": "***123456**",
"qualificacao": {
"codigo": "10",
"descricao": "Diretor"
},
"data_entrada": "2009-11-24",
"faixa_etaria": "41 a 50 anos",
"pais": null,
"representante_legal": null
}
],
"atualizado_em": "2026-09"
}Regras do documento:
- Datas sempre em ISO
AAAA-MM-DDounull. Nunca inventamos campos: o que a Receita não traz vem comonull. cnpjtem 14 caracteres sem pontuação, em maiúsculas;cnpj_formatadotem a máscara00.000.000/0000-00.situacao_cadastral.descricaoé uma deATIVA,BAIXADA,INAPTA,SUSPENSA,NULA.capital_socialé número (reais, duas casas).socios[].cpf_cnpjvem exatamente como a Receita publica: CPF mascarado (***123456**) para pessoa física. Esses são dados pessoais de acesso público; veja a seção sobre LGPD na política de privacidade.atualizado_emé o mês do lote de dados abertos em uso.
Erros
| HTTP | code | Quando | Corpo |
|---|---|---|---|
| 400 | invalid_cnpj | CNPJ com tamanho ou dígito verificador inválido | {"status":"ERROR","message":"CNPJ inválido: dígito verificador não confere","code":"invalid_cnpj"} |
| 400 | validation_error | Parâmetro fora do esperado (ex.: formato diferente de completo ou simplificado) | {"status":"ERROR","message":"...","code":"validation_error"} |
| 401 | unauthorized | Sem chave (e sem sessão do site), ou chave inválida ou revogada | {"status":"ERROR","message":"Crie uma conta grátis para consultar","code":"unauthorized"} |
| 404 | not_found | CNPJ válido, mas ausente no lote atual | {"status":"ERROR","message":"CNPJ não encontrado","code":"not_found"} |
| 429 | rate_limited | Limite por minuto excedido | {"status":"ERROR","message":"Limite de consultas por minuto excedido","code":"rate_limited","retry_after":37} + header Retry-After |
| 429 | quota_exceeded | Cota mensal esgotada | {"status":"ERROR","message":"Cota mensal esgotada","code":"quota_exceeded","upgrade_url":"https://apipj.com.br/precos"} |
| 5xx | internal_error | Falha do nosso lado | {"status":"ERROR","message":"Erro interno","code":"internal_error"}; confira /status |
Todo erro tem a forma {status:"ERROR", message, code}; code é estável e em snake_case, message é texto em português para humanos.
Formato simplificado
Acrescente ?formato=simplificado para receber um formato plano, com os campos já formatados para exibir: abertura (DD/MM/AAAA), situacao, tipo, nome, fantasia, porte, natureza_juridica ("205-4 - Sociedade Anônima Fechada"), atividade_principal ([{code, text}]), atividades_secundarias, logradouro, numero, complemento, municipio, bairro, uf, cep ("80.730-001"), email, telefone ("(41) 3028-7828"), data_situacao, cnpj (com máscara), ultima_atualizacao, status, efr, motivo_situacao, situacao_especial, data_situacao_especial, capital_social (string), simples, simei, qsa (sócios), extra e billing.
Diferenças em relação ao completo: textos vazios vêm como "" em vez de null, códigos e descrições aparecem juntos em um só campo (natureza_juridica, qsa[].qual) e endereço e telefones vêm como texto em campos planos (o completo os detalha em objetos). billing.database vem sempre true, porque toda resposta sai da base mensal. Os limites, a cota e os erros são os mesmos nos dois formatos.
curl -s "https://apipj.com.br/v1/cnpj/11378117000120?formato=simplificado" \
-H "Accept: application/json" \
-H "Authorization: Bearer apipj_live_SUA_CHAVE"const resp = await fetch("https://apipj.com.br/v1/cnpj/11378117000120?formato=simplificado", {
headers: {
Accept: "application/json",
Authorization: "Bearer apipj_live_SUA_CHAVE",
},
});
if (!resp.ok) {
const erro = await resp.json().catch(() => ({}));
throw new Error(`HTTP ${resp.status}: ${erro.message ?? "erro"}`);
}
const dados = await resp.json();
console.log(dados.nome, dados.situacao);
console.log("restam no minuto:", resp.headers.get("X-RateLimit-Remaining"));import requests
r = requests.get(
"https://apipj.com.br/v1/cnpj/11378117000120?formato=simplificado",
headers={
"Accept": "application/json",
"Authorization": "Bearer apipj_live_SUA_CHAVE",
},
timeout=10,
)
if r.status_code == 429:
raise SystemExit(f"limite: tente em {r.headers.get('Retry-After')} s")
r.raise_for_status()
dados = r.json()
print(dados["nome"], dados["situacao"])<?php
$ch = curl_init("https://apipj.com.br/v1/cnpj/11378117000120?formato=simplificado");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Authorization: Bearer apipj_live_SUA_CHAVE",
],
]);
$corpo = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("HTTP $status: $corpo");
}
$dados = json_decode($corpo, true, 512, JSON_THROW_ON_ERROR);
echo $dados["nome"], " - ", $dados["situacao"], PHP_EOL;using System.Net.Http.Headers;
using System.Text.Json;
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "apipj_live_SUA_CHAVE");
using var resp = await http.GetAsync("https://apipj.com.br/v1/cnpj/11378117000120?formato=simplificado");
if (!resp.IsSuccessStatusCode)
throw new HttpRequestException($"HTTP {(int)resp.StatusCode}: {await resp.Content.ReadAsStringAsync()}");
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var raiz = doc.RootElement;
Console.WriteLine(raiz.GetProperty("nome"));Resposta 200 (formato simplificado)
{
"abertura": "24/11/2009",
"situacao": "ATIVA",
"tipo": "MATRIZ",
"nome": "LEADS2B S/A",
"fantasia": "LEADS2B.COM",
"porte": "DEMAIS",
"natureza_juridica": "205-4 - Sociedade Anônima Fechada",
"atividade_principal": [
{
"code": "63.11-9-00",
"text": "Tratamento de dados, provedores de serviços de aplicação e serviços de hospedagem na internet"
}
],
"atividades_secundarias": [
{
"code": "85.99-6-04",
"text": "Treinamento em desenvolvimento profissional e gerencial"
}
],
"logradouro": "RUA PADRE ANCHIETA",
"numero": "2285",
"complemento": "CONJ 1603 ANDAR 16 COND BUSINESS CENTER",
"municipio": "CURITIBA",
"bairro": "BIGORRILHO",
"uf": "PR",
"cep": "80.730-001",
"email": "contabilidade@leads2b.com",
"telefone": "(41) 3028-7828",
"data_situacao": "24/11/2009",
"cnpj": "11.378.117/0001-20",
"ultima_atualizacao": "2026-09-14T00:00:00.000Z",
"status": "OK",
"efr": "",
"motivo_situacao": "",
"situacao_especial": "",
"data_situacao_especial": "",
"capital_social": "218878.00",
"simples": {
"optante": false,
"data_opcao": "24/11/2009",
"data_exclusao": "31/12/2019",
"ultima_atualizacao": "2026-09-14T00:00:00.000Z"
},
"simei": {
"optante": false,
"data_opcao": null,
"data_exclusao": null,
"ultima_atualizacao": "2026-09-14T00:00:00.000Z"
},
"qsa": [
{
"nome": "FULANO DE TAL",
"qual": "10-Diretor",
"pais_origem": "",
"nome_rep_legal": "",
"qual_rep_legal": ""
}
],
"extra": {},
"billing": {
"free": true,
"database": true
}
}GET /v1/valida/{cnpj}
Valida formato e dígito verificador, inclusive de CNPJ alfanumérico. Não exige chave, não consome cota e não consulta a base (um CNPJ pode ser válido e não existir).
curl -s "https://apipj.com.br/v1/valida/12ABC34501DE35" \
-H "Accept: application/json"
# sem chave e sem cota (rota aberta)const resp = await fetch("https://apipj.com.br/v1/valida/12ABC34501DE35", {
headers: {
Accept: "application/json",
// Authorization: "Bearer apipj_live_...", // opcional nesta rota
},
});
if (!resp.ok) {
const erro = await resp.json().catch(() => ({}));
throw new Error(`HTTP ${resp.status}: ${erro.message ?? "erro"}`);
}
const dados = await resp.json();
console.log(dados.valido, dados.formatado);
console.log("restam no minuto:", resp.headers.get("X-RateLimit-Remaining"));import requests
r = requests.get(
"https://apipj.com.br/v1/valida/12ABC34501DE35",
headers={
"Accept": "application/json",
# "Authorization": "Bearer apipj_live_...", # opcional nesta rota
},
timeout=10,
)
if r.status_code == 429:
raise SystemExit(f"limite: tente em {r.headers.get('Retry-After')} s")
r.raise_for_status()
dados = r.json()
print(dados["valido"], dados["formatado"])<?php
$ch = curl_init("https://apipj.com.br/v1/valida/12ABC34501DE35");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
// "Authorization: Bearer apipj_live_...", // opcional
],
]);
$corpo = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("HTTP $status: $corpo");
}
$dados = json_decode($corpo, true, 512, JSON_THROW_ON_ERROR);
echo var_export($dados["valido"], true), " - ", $dados["formatado"], PHP_EOL;using System.Net.Http.Headers;
using System.Text.Json;
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "apipj_live_..."); // opcional
using var resp = await http.GetAsync("https://apipj.com.br/v1/valida/12ABC34501DE35");
if (!resp.IsSuccessStatusCode)
throw new HttpRequestException($"HTTP {(int)resp.StatusCode}: {await resp.Content.ReadAsStringAsync()}");
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var raiz = doc.RootElement;
Console.WriteLine(raiz.GetProperty("valido"));Resposta 200
{
"cnpj": "12ABC34501DE35",
"valido": true,
"formatado": "12.ABC.345/01DE-35",
"alfanumerico": true,
"erro": null
}Com DV errado a resposta continua 200, com valido: false e erro explicando ("Dígito verificador não confere"). Só devolvemos 400 quando o parâmetro está vazio ou passa de 18 caracteres.
GET /v1/status
Estado da API e do dataset. Sem chave, sem cota. Use para monitorar e para saber o mês dos dados antes de uma carga em lote.
curl -s "https://apipj.com.br/v1/status" \
-H "Accept: application/json"
# sem chave e sem cota (rota aberta)const resp = await fetch("https://apipj.com.br/v1/status", {
headers: {
Accept: "application/json",
// Authorization: "Bearer apipj_live_...", // opcional nesta rota
},
});
if (!resp.ok) {
const erro = await resp.json().catch(() => ({}));
throw new Error(`HTTP ${resp.status}: ${erro.message ?? "erro"}`);
}
const dados = await resp.json();
console.log(dados.status, dados.dataset_month);
console.log("restam no minuto:", resp.headers.get("X-RateLimit-Remaining"));import requests
r = requests.get(
"https://apipj.com.br/v1/status",
headers={
"Accept": "application/json",
# "Authorization": "Bearer apipj_live_...", # opcional nesta rota
},
timeout=10,
)
if r.status_code == 429:
raise SystemExit(f"limite: tente em {r.headers.get('Retry-After')} s")
r.raise_for_status()
dados = r.json()
print(dados["status"], dados["dataset_month"])<?php
$ch = curl_init("https://apipj.com.br/v1/status");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
// "Authorization: Bearer apipj_live_...", // opcional
],
]);
$corpo = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("HTTP $status: $corpo");
}
$dados = json_decode($corpo, true, 512, JSON_THROW_ON_ERROR);
echo $dados["status"], " - ", $dados["dataset_month"], PHP_EOL;using System.Net.Http.Headers;
using System.Text.Json;
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "apipj_live_..."); // opcional
using var resp = await http.GetAsync("https://apipj.com.br/v1/status");
if (!resp.IsSuccessStatusCode)
throw new HttpRequestException($"HTTP {(int)resp.StatusCode}: {await resp.Content.ReadAsStringAsync()}");
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var raiz = doc.RootElement;
Console.WriteLine(raiz.GetProperty("status"));Resposta 200
{
"status": "OK",
"dataset_month": "2026-09",
"rows": 65000000,
"version": "1.0.0",
"time": "2026-10-09T12:00:00.000Z"
}CNPJ alfanumérico
Desde 31/07/2026 a Receita Federal emite CNPJs com letras nas 12 primeiras posições (raiz de 8 e ordem de 4); os dois dígitos verificadores continuam numéricos. O formato é [A-Z0-9]{12}[0-9]{2}. O cálculo do DV usa módulo 11 com os pesos de sempre, mas o valor de cada caractere é o seu código ASCII menos 48 (0→0 … 9→9, A→17 … Z→42).
Exemplo válido para testes: 12.ABC.345/01DE-35. A API aceita letras minúsculas e qualquer pontuação na entrada e normaliza antes de validar. Nos nossos documentos o campo cnpj vem sempre em maiúsculas sem pontuação, e cnpj_formatado com a máscara tradicional.
Se o seu sistema valida CNPJ localmente, troque a rotina pelo novo algoritmo ou use /v1/valida (grátis, sem cota) enquanto atualiza o seu sistema.
Boas práticas
- Cache por CNPJ. A base muda uma vez por mês; guarde a resposta por até 30 dias (ou até
atualizado_emmudar em/v1/status). Isso reduz seu consumo de cota e a latência para zero na maioria das consultas repetidas. - Respeite
Retry-After. Em 429, espere o número de segundos indicado antes de tentar de novo; não faça retry imediato. Para 5xx, use backoff exponencial com jitter (1 s, 2 s, 4 s) e no máximo 3 tentativas. - Leia
X-RateLimit-RemainingeX-Quota-Remaining. Em cargas em lote, controle o ritmo peloX-RateLimit-Limitem vez de disparar tudo e esperar o 429. - Valide antes de consultar.
/v1/valida(ou o algoritmo local) evita gastar cota com CNPJs digitados errado. - Trate
null. Muitos campos (e-mail, telefones, nome fantasia, situação especial) vêmnulllegitimamente. - Timeout de 10 s no cliente e
Accept: application/json. - Não dependa de ordem de chaves no JSON nem de campos fora desta documentação; novos campos podem ser acrescentados sem aviso (nunca removidos sem mudança de versão).
Conta, chaves e cobrança (rotas do painel)
Estas rotas existem para o painel e usam sessão por cookie, não chave de API. Estão aqui por transparência; para integrar, use as rotas públicas acima.
| Rota | Descrição | |
|---|---|---|
POST /v1/auth/signup | {email, password, name, cpf_cnpj?, accept_tos: true} cria a conta, a sessão e a primeira chave | |
POST /v1/auth/login / POST /v1/auth/logout | Sessão web | |
GET /v1/auth/providers | Provedores de login disponíveis (`{google: true | false}`) |
GET /v1/auth/google/start, GET /v1/auth/google/callback | Entrar, criar conta ou vincular a conta Google (OpenID Connect com PKCE); POST /v1/auth/google/unlink desvincula | |
GET /v1/me | Usuário, plano, validade e uso do mês | |
GET /v1/keys, POST /v1/keys, DELETE /v1/keys/{id} | Lista, cria (máximo 5 ativas) e revoga chaves | |
GET /v1/usage | Uso do período, limites e reset (aceita sessão ou chave) | |
POST /v1/billing/checkout | {plan} devolve {url} da página de pagamento do Asaas (cartão de crédito) | |
POST /v1/billing/cancel | Cancela a assinatura; o plano continua até o fim do período pago |
Rotas mutáveis exigem o header X-Requested-With: apipj e Origin da mesma origem. Nenhum dado de cartão passa pelos nossos servidores.
Changelog
- 09/10/2026: versão inicial da documentação (v1).