apipj API

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.

Operations 35

GET /v1/status Status do serviço e do dataset
GET /v1/valida/{cnpj} Valida formato e dígitos verificadores de um CNPJ
GET /v1/cnpj/{cnpj} Consulta os dados cadastrais de um CNPJ
GET /v1/busca Busca CNPJs ativos por atividade (CNAE principal) e município
GET /v1/plans Planos e limites públicos
POST /v1/auth/signup Cria conta, sessão e a chave inicial
POST /v1/auth/login Login com e-mail e senha (cookie de sessão)
POST /v1/auth/logout Encerra a sessão atual
POST /v1/auth/accept-tos Registra o aceite da versão atual dos termos
POST /v1/auth/password Troca a senha (encerra as outras sessões)
GET /v1/keys Lista as chaves ativas (só o prefixo)
POST /v1/keys Cria uma chave (mostrada uma única vez)
DELETE /v1/keys/{id} Revoga uma chave imediatamente
GET /v1/me Usuário, plano, validade e uso do mês
POST /v1/avisos/{id}/ciencia Registra a ciência de um aviso do painel
GET /v1/usage Uso do mês, limites do plano e data de reset
POST /v1/billing/checkout Inicia a assinatura de um plano pago
GET /v1/billing/pending Pagamento pendente do pedido em andamento
POST /v1/billing/cancel-pending Cancela o pedido ainda não pago
POST /v1/billing/sync Confere o pagamento do pedido no Asaas e ativa o plano
POST /v1/billing/cancel Cancela a assinatura (plano vale até o fim do período pago) ou exerce o arrependimento
POST /v1/billing/portal Portal do cliente do Stripe (cartão e faturas)
POST /v1/account/close Encerra a conta (carência de 30 dias para reativar)
GET /v1/auth/providers Formas de login disponíveis
GET /v1/auth/google/start Inicia o login com Google (navegação de topo, responde 302)
GET /v1/auth/google/callback Retorno do Google (responde 302)
GET /v1/auth/google/pending Dados da conta Google aguardando confirmação do cadastro
POST /v1/auth/google/complete Confirma o cadastro com Google (aceite dos termos)
POST /v1/auth/google/unlink Desvincula o Google da conta
POST /webhooks/asaas Webhook do Asaas (uso interno)
POST /webhooks/stripe Webhook do Stripe (uso interno)
GET /v1/oauth/pedido/{id} Pedido de conexão de um aplicativo (página /autorizar)
POST /v1/oauth/pedido/{id}/decisao Autoriza ou recusa o aplicativo do pedido
GET /v1/oauth/aplicativos Aplicativos conectados à conta (OAuth)
DELETE /v1/oauth/aplicativos/{id} Desconecta um aplicativo (revoga os tokens na hora)

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/apipj:apipj-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

apipj-api-openapi.json Raw ↑
{"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/busca":{"get":{"summary":"Busca CNPJs ativos por atividade (CNAE principal) e município","tags":["Consulta"],"description":"Lista estabelecimentos **ativos** pela atividade econômica principal (`cnae`) e/ou pelo município (`municipio`); pelo menos um dos dois filtros é obrigatório (senão 400 `validation_error`). Autenticação como em `/v1/cnpj`: `Authorization: Bearer <chave>` (preferido), `X-API-Key` ou o cookie de sessão do site; sem autenticação, 401 `unauthorized`. Paginação por cursor: a página tem no máximo o limite por minuto do plano (ou `limite`, de 1 até esse valor; teto de 1000) e é cortada pelo que ainda resta no minuto e na cota do mês. Envie `proximo_cursor` como `cursor` para a página seguinte; `null` indica o fim. **Cada CNPJ devolvido consome 1 do limite por minuto e 1 da cota mensal**, na mesma contabilidade de `/v1/cnpj` (mesma chave, mesma cota). Página vazia não consome nada. Os resultados não trazem o quadro de sócios (`socios` no formato completo, `qsa` no simplificado): sócios só na consulta individual. CNPJs cujo titular se opôs à busca ficam de fora (e do `total`). Resposta: `{dataset_month, total, resultados, proximo_cursor}`, com os cabeçalhos X-RateLimit-* e X-Quota-*. Erros: 400 `validation_error` ou `cursor_invalido` (cursor de outra busca, de outro mês da base ou malformado), 401 `unauthorized`, 429 `rate_limited` (com `Retry-After`) ou `quota_exceeded` (com `upgrade_url`), 503 `busca_indisponivel` (índice em atualização) ou `busca_em_breve` (antes do início da vigência).","parameters":[{"schema":{"type":"string","maxLength":20},"in":"query","name":"cnae","required":false,"description":"CNAE da atividade principal, 7 dígitos, com ou sem pontuação (4781400 ou 47.81-4-00)"},{"schema":{"type":"string","maxLength":20},"in":"query","name":"municipio","required":false,"description":"Município: código da Receita Federal (4 dígitos, o `endereco.municipio.codigo_rfb`) ou do IBGE (7 dígitos)"},{"schema":{"type":"string","maxLength":512},"in":"query","name":"cursor","required":false,"description":"Valor de `proximo_cursor` da página anterior (mesmos filtros)"},{"schema":{"type":"string","enum":["completo","simplificado"],"default":"completo"},"in":"query","name":"formato","required":false,"description":"Formato de cada resultado, como em `/v1/cnpj` (sem os sócios)"},{"schema":{"type":"integer","minimum":1},"in":"query","name":"limite","required":false,"description":"Tamanho máximo da página, de 1 até o limite por minuto do plano (padrão: esse limite)"},{"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}],"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, mais `billing {provider, test_mode, available, requires_document}` (provedor de pagamento e se as assinaturas estão abertas).","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,"description":"Nome, em uma linha: quebra de linha ou caractere de controle → 400 `validation_error` (`field: \"name\"`); espaços repetidos viram um só"},"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`, `auth {password, google, google_email}` (formas de entrar: senha própria, Google vinculado e o e-mail Google mascarado), `avisos` (avisos do painel ativos na data e ainda sem ciência da conta: `[{id, titulo, texto, links: [{rotulo, url}]}]`; a primeira devolução registra a exibição), `checkout {pending, plan, plan_name}` (pedido de assinatura aguardando pagamento, lido só do banco local, sem consultar o provedor: com `pending: true` o painel mostra a faixa de pagamento pendente e busca os detalhes em `GET /v1/billing/pending`) e `billing {provider, test_mode, available, requires_document, portal}` (provedor de pagamento: `stripe` ou `asaas`; modo de teste; se a conta pode assinar agora; se o checkout pede CPF/CNPJ; se há portal do cliente para trocar cartão e ver faturas).","security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/avisos/{id}/ciencia":{"post":{"summary":"Registra a ciência de um aviso do painel","tags":["Conta"],"description":"Grava a data e hora em que a conta deu ciência do aviso (idempotente: vale o primeiro registro). 404 `not_found` para aviso inexistente ou fora da janela de exibição. Requer o header `X-Requested-With: apipj`.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64},"in":"path","name":"id","required":true}],"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":"Provedor em `GET /v1/plans` → `billing.provider`. **Stripe:** cria (ou reaproveita, com `reused: true`) uma Checkout Session de assinatura mensal e devolve `{url, plan, value, reused, return_supported: true}`; `url` é a página do Stripe (checkout.stripe.com), que pede o cartão e o CPF/CNPJ (nada disso passa por esta API) e volta para `/painel?pagamento=retorno&session_id=…` (ou `/painel?pagamento=cancelado`). Sem `cpf_cnpj`. Em produção com o Stripe em modo de teste, só contas liberadas assinam: as demais recebem 403 `checkout_indisponivel` (\"Assinaturas abrindo em breve\"); preço do Stripe divergente de `config/plans.json`: 503 `checkout_indisponivel`. **Asaas:** cria (ou reaproveita) a assinatura no Asaas e devolve `{url, plan, value, reused, return_supported}`: `url` é a fatura hospedada, onde o cliente informa o cartão (nenhum dado de cartão passa por esta API). A assinatura é criada com retorno automático para `/painel?pagamento=retorno` (`return_supported: true`: abra a fatura na mesma aba); se o Asaas recusar o retorno (site não cadastrado na conta Asaas), ela é refeita sem ele e `return_supported` vem `false` (abra a fatura em outra aba e mantenha o painel consultando `POST /v1/billing/sync`). Com `reused: true` a fatura pendente do mesmo plano foi reaproveitada. Exige CPF/CNPJ: se o cadastro não tem, envie `cpf_cnpj` no corpo (fica gravado na conta). Pedido anterior já pago no Asaas e ainda não ativado: 409 `checkout_already_paid` (o plano é ativado na hora e nada é recriado). Conta em revisão por contestação de pagamento: 403 `account_under_review`. Pedidos simultâneos da mesma conta são atendidos um de cada vez (o segundo do mesmo plano reaproveita a fatura do primeiro). Limite: 10 por minuto por IP e, por usuário, 6 por minuto e 30 por hora (429 `rate_limited` com `Retry-After`). 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/pending":{"get":{"summary":"Pagamento pendente do pedido em andamento","tags":["Billing"],"description":"`{pending: null}` ou `{pending: {plan, plan_name, value, invoice_url, due_date, created_at, return_supported}}`: a fatura ainda não paga da assinatura criada pelo checkout (consulta o Asaas; guardada por 30 s por usuário). `invoice_url` reaproveita a mesma fatura (\"Continuar pagamento\"). Falha do Asaas: 502 `billing_unavailable`. `GET /v1/me` traz `checkout.pending` (só o banco local) para decidir se vale consultar esta rota.","security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/billing/cancel-pending":{"post":{"summary":"Cancela o pedido ainda não pago","tags":["Billing"],"description":"Remove no Asaas a assinatura criada pelo checkout que ainda não foi paga e limpa o pedido: `{cancelled: true, plan, plan_name, plan_valid_until}` (o plano atual da conta, que não muda). 409 `no_pending_checkout` se não há pedido pendente; 409 `checkout_already_paid` se o Asaas já confirmou o pagamento (o plano é ativado na hora; para não renovar, use `POST /v1/billing/cancel`). Falha do Asaas: 502 `billing_unavailable`, nada muda. Numa troca de plano a assinatura anterior já foi removida no checkout: o plano atual segue até `plan_valid_until`, sem renovação. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/billing/sync":{"post":{"summary":"Confere o pagamento do pedido no Asaas e ativa o plano","tags":["Billing"],"description":"Para a volta do Asaas (`/painel?pagamento=retorno`) e para o painel com pedido em andamento: reconsulta no Asaas as cobranças da assinatura da conta e, se o Asaas diz `CONFIRMED`/`RECEIVED`, ativa o plano pelo mesmo caminho do webhook (idempotente com ele: uma só ativação). Nunca ativa sem a confirmação do Asaas. Devolve `{status, plan, plan_name, plan_valid_until, limits: {rpm, monthly_quota}, activated, checked}`: `status` = `active` (plano pago vigente e nenhum pedido pendente), `pending` (pedido aguardando o pagamento; `plan` é o plano pedido) ou `none` (nenhum pedido e plano gratuito); `activated` = esta chamada ativou o plano; `checked` = o Asaas foi consultado nesta chamada (`false`: sem pedido pendente, consulta recente, teto de consultas ou Asaas indisponível; a resposta sai do estado local, sem erro). Limite: 30 por minuto por usuário (429 `rate_limited` com `Retry-After`). Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"session_id":{"type":"string","minLength":1,"maxLength":255,"description":"Stripe: o session_id do retorno do Checkout (/painel?pagamento=retorno&session_id=…); precisa ser da conta (senão 403 checkout_session_mismatch)"}}}}}},"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":"No provedor que ativou o plano: no Stripe, `cancel_at_period_end` (a assinatura não renova e acaba no fim do período pago); no Asaas, remove a assinatura. 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`. Um pedido de estorno por contratação: pedidos repetidos ou simultâneos recebem 400 `refund_not_eligible` (`ja_estornado`); erro do Asaas responde 502 e o pedido pode ser repetido; sem resposta do Asaas (timeout), 502 com o pedido mantido e orientação para falar com o suporte. 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: estorno integral se 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); uso igual ou acima da cota: 400 refund_not_eligible (uso_excessivo)"}}}}}},"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/billing/portal":{"post":{"summary":"Portal do cliente do Stripe (cartão e faturas)","tags":["Billing"],"description":"Plano pago ativado pelo Stripe: devolve `{url}` de uma sessão do portal do cliente do Stripe (billing.stripe.com, válida por pouco tempo; abra na hora), com volta para `/painel`. O portal serve só para trocar o cartão e ver as faturas; cancelar e desistir continuam em `POST /v1/billing/cancel`. Sem assinatura no Stripe: 400 `no_subscription`. Falha do Stripe: 502 `billing_unavailable`. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{}}}}},"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`, `/sandbox`, `/consulta-cnpj-em-lote`, `/painel?assinar={id}` para um plano pago público de `config/plans.json` ou `/autorizar?pedido={id}` (página de consentimento do OAuth do MCP; id de 43 caracteres base64url) (comparação exata, codificado na URL; 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`; com `next=/painel?assinar={id}`, vai a `/painel?assinar={id}&boas-vindas=1`), 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"}}}},"/webhooks/stripe":{"post":{"summary":"Webhook do Stripe (uso interno)","tags":["Interno"],"description":"Recebe eventos de checkout, fatura, assinatura, estorno e disputa. Exige o cabeçalho `Stripe-Signature` válido (HMAC-SHA256 com o segredo do endpoint, tolerância de 300 s). Responde 200 assim que o evento é gravado; o processamento é assíncrono e idempotente pelo `id` do evento.","responses":{"200":{"description":"Default Response"}}}},"/v1/oauth/pedido/{id}":{"get":{"summary":"Pedido de conexão de um aplicativo (página /autorizar)","tags":["Conta"],"description":"Dados do pedido criado por `GET /oauth/authorize` (10 minutos): `cliente {nome, host, tipo}` (host do client_id quando o cliente se identifica por URL), `redirect {host, loopback}` (para onde a pessoa volta), `loopback_apenas`, `acesso` (o que a autorização permite), `expira_em`, `conta {email, nome}` da sessão atual ou `null` e `tos_version`. 404 `pedido_expirado` se não existe, expirou ou já foi decidido.","parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/v1/oauth/pedido/{id}/decisao":{"post":{"summary":"Autoriza ou recusa o aplicativo do pedido","tags":["Conta"],"description":"`{autorizar: true|false}` com sessão. Uso único: o pedido some depois da decisão. Devolve `{redirect}`, a URL de volta ao aplicativo com `code` e `state` (ou `error=access_denied`) e `iss`; a página navega até ela. 401 sem sessão; 404 `pedido_expirado`. Requer o header `X-Requested-With: apipj`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["autorizar"],"additionalProperties":false,"properties":{"autorizar":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$"},"in":"path","name":"id","required":true}],"security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/oauth/aplicativos":{"get":{"summary":"Aplicativos conectados à conta (OAuth)","tags":["Conta"],"description":"Concessões ativas: `{aplicativos: [{id, nome, host, redirect_host, tipo, criado_em, usado_em}]}`. Cada conexão autorizada (por exemplo, o conector do Claude) aparece uma vez.","security":[{"cookie":[]}],"responses":{"200":{"description":"Default Response"}}}},"/v1/oauth/aplicativos/{id}":{"delete":{"summary":"Desconecta um aplicativo (revoga os tokens na hora)","tags":["Conta"],"description":"Revoga a concessão: o token de acesso e o refresh token do aplicativo param de valer imediatamente (o MCP responde 401 e o aplicativo pede para conectar de novo). 404 se não existe ou já foi revogada. Requer o header `X-Requested-With: apipj`.","parameters":[{"schema":{"type":"integer","minimum":1},"in":"path","name":"id","required":true}],"security":[{"cookie":[]}],"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 (exige chave de API ou sessão do site)"},{"name":"Conta","description":"Cadastro, login e perfil (sessão por cookie)"},{"name":"Chaves","description":"Chaves de API"},{"name":"Billing","description":"Assinaturas (Stripe; Asaas como alternativa)"},{"name":"Interno","description":"Rotas internas (webhooks)"}]}