{"openapi":"3.1.0","info":{"title":"apipj","version":"0.1.0","description":"API de consulta de CNPJ a partir dos dados abertos da Receita Federal. Formato `completo` (padrão, documento estruturado) ou `simplificado` (formato plano com campos já formatados). Suporte a CNPJ alfanumérico.","contact":{"email":"brunogalizzi@masterbi.com"}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Authorization: Bearer <chave>"},"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key"},"cookie":{"type":"apiKey","in":"cookie","name":"__Host-apipj_session"}},"schemas":{}},"paths":{"/v1/status":{"get":{"summary":"Status do serviço e do dataset","tags":["Público"],"description":"Sem autenticação. Informa o mês do dataset da Receita Federal carregado e a quantidade de CNPJs.","responses":{"200":{"description":"Default Response"}}}},"/v1/valida/{cnpj}":{"get":{"summary":"Valida formato e dígitos verificadores de um CNPJ","tags":["Público"],"description":"Sem autenticação e sem consumo de cota. Aceita CNPJ numérico ou alfanumérico (IN RFB 2.229/2024), com ou sem pontuação. Não consulta a base.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":32},"in":"path","name":"cnpj","required":true,"description":"CNPJ com ou sem pontuação (numérico ou alfanumérico)"}],"responses":{"200":{"description":"Default Response"}}}},"/v1/cnpj/{cnpj}":{"get":{"summary":"Consulta os dados cadastrais de um CNPJ","tags":["Consulta"],"description":"Autenticação obrigatória: `Authorization: Bearer <chave>` (preferido), `X-API-Key: <chave>` ou `?token=<chave>` (obsoleto); no site, o cookie de sessão (mesma origem) também vale. Valem o limite por minuto e a cota mensal do plano do usuário (chaves e sessão somam na mesma cota). Sem autenticação: 401 `unauthorized`. Cabeçalhos sempre presentes: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-Quota-Limit, X-Quota-Remaining, X-Quota-Reset. Erros: 400 `invalid_cnpj`, 401 `unauthorized`, 404 `not_found`, 429 `rate_limited` ou `quota_exceeded` (com `Retry-After` / `upgrade_url`).","parameters":[{"schema":{"type":"string","enum":["completo","simplificado"],"default":"completo"},"in":"query","name":"formato","required":false,"description":"Formato da resposta: `completo` (padrão: documento estruturado, com códigos e descrições) ou `simplificado` (formato plano para integrações que preferem campos já formatados: datas DD/MM/AAAA, CNPJ, CEP e telefone com máscara)"},{"schema":{"type":"string","maxLength":80,"deprecated":true},"in":"query","name":"token","required":false,"description":"Chave de API na query string (obsoleto: use o header Authorization)","deprecated":true},{"schema":{"type":"string","minLength":1,"maxLength":32},"in":"path","name":"cnpj","required":true,"description":"CNPJ com ou sem pontuação (numérico ou alfanumérico)"}],"security":[{"bearer":[]},{"apiKey":[]},{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/plans":{"get":{"summary":"Planos e limites públicos","tags":["Público"],"description":"Mesmo conteúdo de config/plans.json, só os planos públicos.","responses":{"200":{"description":"Default Response"}}}},"/v1/auth/signup":{"post":{"summary":"Cria conta, sessão e a chave inicial","tags":["Conta"],"description":"Devolve a chave de API uma única vez. Exige `accept_tos: true` (grava versão e data do aceite); `tos_version` é opcional e, se enviada, precisa ser a versão atual dos termos (senão 400 `tos_required`). Limite: 20 cadastros por IP por dia. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password","name","accept_tos"],"additionalProperties":false,"properties":{"email":{"type":"string","minLength":5,"maxLength":254},"password":{"type":"string","minLength":1,"maxLength":256},"name":{"type":"string","minLength":1,"maxLength":120},"cpf_cnpj":{"type":"string","maxLength":24,"description":"CPF ou CNPJ (opcional no gratuito, obrigatório para assinar)"},"accept_tos":{"type":"boolean"},"tos_version":{"type":"string","maxLength":20,"description":"Versão dos termos exibida ao usuário (opcional). Se divergir da versão atual, a resposta é 400 `tos_required` com a versão vigente."}}}}}},"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/login":{"post":{"summary":"Login com e-mail e senha (cookie de sessão)","tags":["Conta"],"description":"Resposta genérica em falha (também para conta criada com o Google, que não tem senha). Bloqueio de 15 minutos após 5 falhas (e-mail + IP) ou 20 falhas (IP). Conta encerrada há menos de 30 dias é reativada pelo login (`reactivated: true`). Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"additionalProperties":false,"properties":{"email":{"type":"string","minLength":1,"maxLength":254},"password":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/logout":{"post":{"summary":"Encerra a sessão atual","tags":["Conta"],"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/accept-tos":{"post":{"summary":"Registra o aceite da versão atual dos termos","tags":["Conta"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accept_tos"],"additionalProperties":false,"properties":{"accept_tos":{"type":"boolean"}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/password":{"post":{"summary":"Troca a senha (encerra as outras sessões)","tags":["Conta"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["current_password","new_password"],"additionalProperties":false,"properties":{"current_password":{"type":"string","minLength":1,"maxLength":256},"new_password":{"type":"string","minLength":1,"maxLength":256}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/keys":{"get":{"summary":"Lista as chaves ativas (só o prefixo)","tags":["Chaves"],"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}},"post":{"summary":"Cria uma chave (mostrada uma única vez)","tags":["Chaves"],"description":"Máximo de 5 chaves ativas por conta e 10 criações por hora. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":60}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/keys/{id}":{"delete":{"summary":"Revoga uma chave imediatamente","tags":["Chaves"],"parameters":[{"schema":{"type":"integer","minimum":1},"in":"path","name":"id","required":true}],"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/me":{"get":{"summary":"Usuário, plano, validade e uso do mês","tags":["Conta"],"description":"Devolve `user`, o plano efetivo (`plan` = id, `plan_name`), `plan_valid_until`, `cancel_requested`, `plan_started_at` e `refund_eligible_until` (plano pago: confirmação do primeiro pagamento e fim dos 7 dias de arrependimento, ou `null`), `limits`, `usage` do mês, `tos_required` e `auth {password, google, google_email}` (formas de entrar: senha própria, Google vinculado e o e-mail Google mascarado).","security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/usage":{"get":{"summary":"Uso do mês, limites do plano e data de reset","tags":["Conta"],"description":"Aceita sessão (cookie) ou chave de API. `used`/`quota`/`remaining` e `reset_at` (ISO) também aparecem na raiz, além do bloco `usage`.","security":[{"cookie":[]},{"bearer":[]},{"apiKey":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/billing/checkout":{"post":{"summary":"Inicia a assinatura de um plano pago","tags":["Billing"],"description":"Cria (ou reaproveita) a assinatura no Asaas e devolve a URL da fatura hospedada, onde o cliente informa o cartão. Nenhum dado de cartão passa por esta API. Exige CPF/CNPJ: se o cadastro não tem, envie `cpf_cnpj` no corpo (fica gravado na conta). Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"additionalProperties":false,"properties":{"plan":{"type":"string","minLength":1,"maxLength":30},"cpf_cnpj":{"type":"string","maxLength":24,"description":"CPF ou CNPJ do titular (só é usado se a conta ainda não tem um)"}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/billing/cancel":{"post":{"summary":"Cancela a assinatura (plano vale até o fim do período pago) ou exerce o arrependimento","tags":["Billing"],"description":"Remove a assinatura no Asaas. O plano continua ativo até `plan_valid_until`; depois cai para o gratuito. Com `{\"refund\": true}` dentro de `refund_eligible_until` (7 dias da confirmação do primeiro pagamento do plano, CDC art. 49; termos §6.7): estorno da primeira cobrança no mesmo cartão e volta imediata ao gratuito. O estorno é integral quando o uso desde a ativação ficou em até 20% da cota mensal; acima disso é limitado à parte não utilizada (`refund_full: false`, cálculo em `usage` e no e-mail); uso igual ou acima da cota, ou fora das condições, responde 400 `refund_not_eligible` com `reason`. Confirmação por e-mail nos dois casos. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"refund":{"type":"boolean","description":"true = desistência em 7 dias com estorno integral"}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/account/close":{"post":{"summary":"Encerra a conta (carência de 30 dias para reativar)","tags":["Conta"],"description":"Confirma a senha (`password`) ou, em conta sem senha própria (criada com o Google), o e-mail da conta digitado de novo (`confirm_email`); cancela a assinatura no Asaas (se houver), revoga todas as chaves, encerra as sessões e marca a conta para eliminação após 30 dias (termos §4.7; política §8). Dentro da carência, um novo login reativa a conta. 400 `validation_error` se faltar o campo exigido pela conta (ver `auth.password` em /v1/me); 401 `unauthorized` se não confere (5 erros em 15 minutos bloqueiam por 15 minutos). Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"password":{"type":"string","minLength":1,"maxLength":256,"description":"Senha da conta (contas com senha própria)"},"confirm_email":{"type":"string","minLength":1,"maxLength":254,"description":"E-mail da conta, digitado de novo (contas sem senha, criadas com o Google)"}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/providers":{"get":{"summary":"Formas de login disponíveis","tags":["Conta"],"description":"`google: true` quando o login com Google está configurado; o site só mostra o botão nesse caso.","responses":{"200":{"description":"Default Response"}}}},"/v1/auth/google/start":{"get":{"summary":"Inicia o login com Google (navegação de topo, responde 302)","tags":["Conta"],"description":"Abrir como link (não por fetch). `intent`: `login` (padrão), `signup` (exige `tos` igual à versão vigente dos termos, marcada no formulário) ou `link` (vincula à conta da sessão atual). `next` só aceita `/painel`, `/precos` ou `/sandbox` (qualquer outro valor vira `/painel`). Grava um estado de uso único (10 min) e o cookie do fluxo, e redireciona ao Google com `state`, `nonce` e PKCE S256. Com o recurso desligado, ou `intent=link` sem sessão ou iniciado por outro site (`Sec-Fetch-Site`), redireciona para `/entrar?erro=google_falhou` ou `google_estado`; `intent=signup` vindo de outro site não vale como aceite (segue para a confirmação).","parameters":[{"schema":{"type":"string","enum":["login","signup","link"],"default":"login"},"in":"query","name":"intent","required":false},{"schema":{"type":"string","maxLength":200},"in":"query","name":"next","required":false},{"schema":{"type":"string","maxLength":20},"in":"query","name":"tos","required":false,"description":"Versão dos termos aceita no formulário (obrigatória em intent=signup)"}],"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/google/callback":{"get":{"summary":"Retorno do Google (responde 302)","tags":["Conta"],"description":"Confere o cookie do fluxo contra `state` (uso único, 10 min), troca o `code` (client_secret + code_verifier) e valida o id_token (RS256/JWKS, iss, aud, exp, nonce, email_verified). Destinos: conta já vinculada → `next` com sessão; `intent=link` → `/painel?google=vinculado`; conta com o mesmo e-mail → vínculo automático só se a posse do e-mail da conta já foi comprovada (conta sem senha própria) e o Google administra o endereço (@gmail.com/@googlemail.com ou `hd` igual ao domínio), senão `/entrar?google=vincular`; conta que já tem outra conta Google não troca o vínculo (`google_ja_vinculado`); sem conta → `intent=signup` com aceite cria a conta sem chave e vai a `/painel?boas-vindas=1` (com `next=/sandbox`, volta a `/sandbox`), senão `/criar-conta?google=1` (confirmação). Erros: `/entrar?erro=google_cancelado|google_estado|google_falhou|google_email_nao_verificado|google_ja_vinculado`.","responses":{"200":{"description":"Default Response"}}}},"/v1/auth/google/pending":{"get":{"summary":"Dados da conta Google aguardando confirmação do cadastro","tags":["Conta"],"description":"Lê o cookie do cadastro pendente (10 min). `{email, name, tos_version}`; 401 `unauthorized` se não houver ou tiver expirado.","responses":{"200":{"description":"Default Response"}}}},"/v1/auth/google/complete":{"post":{"summary":"Confirma o cadastro com Google (aceite dos termos)","tags":["Conta"],"description":"Exige o cookie do cadastro pendente, `accept_tos: true` e `tos_version` igual à vigente (senão 400 `tos_required`). Cria a conta sem senha e sem chave, abre a sessão e apaga o pendente: 201 `{user, next}`. 401 se o pendente expirou; 409 `email_in_use`/`google_in_use` se a conta passou a existir. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accept_tos","tos_version"],"additionalProperties":false,"properties":{"accept_tos":{"type":"boolean"},"tos_version":{"type":"string","maxLength":20}}}}}},"responses":{"200":{"description":"Default Response"}}}},"/v1/auth/google/unlink":{"post":{"summary":"Desvincula o Google da conta","tags":["Conta"],"description":"Só para contas com senha própria; sem senha, 400 `password_required` (seria impossível entrar de novo). Sem Google vinculado, responde ok. Requer o header `X-Requested-With: apipj`.","security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/webhooks/asaas":{"post":{"summary":"Webhook do Asaas (uso interno)","tags":["Interno"],"description":"Recebe eventos de cobrança/assinatura. Exige o header `asaas-access-token` igual ao token cadastrado no Asaas. Responde 200 assim que o evento é gravado; o processamento é assíncrono e idempotente pelo `id` do evento.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","event"],"properties":{"id":{"type":"string","minLength":1,"maxLength":200},"event":{"type":"string","minLength":1,"maxLength":80},"dateCreated":{"type":"string"},"payment":{"type":"object"},"subscription":{"type":"object"}}}}}},"responses":{"200":{"description":"Default Response"}}}}},"servers":[{"url":"https://apipj.com.br"}],"tags":[{"name":"Público","description":"Sem autenticação"},{"name":"Consulta","description":"Consulta de CNPJ (chave opcional)"},{"name":"Conta","description":"Cadastro, login e perfil (sessão por cookie)"},{"name":"Chaves","description":"Chaves de API"},{"name":"Billing","description":"Assinaturas via Asaas"},{"name":"Interno","description":"Rotas internas (webhooks)"}]}