{
  "name": "Radar CNPJ",
  "description": "Pesquise empresas por atividade e lugar. Consulte fichas e acompanhe mudanças cadastrais. Cliente principal: agente de IA.",
  "build": "c52b3d87",
  "base_url": "https://radar-cnpj.com",
  "origin_api": "https://api.radar-cnpj.com",
  "docs": {
    "llms": "https://radar-cnpj.com/llms.txt",
    "llms_full": "https://radar-cnpj.com/llms-full.txt",
    "openapi": "https://radar-cnpj.com/openapi.json",
    "mcp": "https://radar-cnpj.com/mcp",
    "pricing": "https://radar-cnpj.com/api/pricing",
    "billing": "https://radar-cnpj.com/api/billing",
    "human_ui": "https://radar-cnpj.com/",
    "data_indexes": [
      {
        "id": "cnpj",
        "produto": "https://radar-cnpj.com",
        "caminho": "/empresas",
        "title": "Empresas por CNPJ",
        "description": "Estabelecimentos ativos por estado, município e atividade (CNAE), com ficha pública por CNPJ.",
        "hierarchy": "UF → município → atividade (CNAE) → estabelecimentos → ficha por CNPJ",
        "url": "https://api.radar-cnpj.com/empresas/",
        "formats": {
          "html": "https://api.radar-cnpj.com/empresas/",
          "json": "https://api.radar-cnpj.com/empresas/index.json",
          "md": "https://api.radar-cnpj.com/empresas/index.md",
          "okf": "https://api.radar-cnpj.com/empresas/index.okf.md"
        },
        "llms": "https://api.radar-cnpj.com/empresas/llms.txt",
        "openapi": "https://api.radar-cnpj.com/empresas/openapi.json",
        "mcp": "https://api.radar-cnpj.com/empresas/mcp",
        "okf": "https://api.radar-cnpj.com/empresas/okf/index.md",
        "access": "public-read-only",
        "pagination": {
          "max_items": 20,
          "next": "links.proximo"
        },
        "updates": "manual"
      },
      {
        "id": "cep",
        "produto": "https://pontofato.com",
        "caminho": "/enderecos",
        "title": "CEPs e endereços",
        "description": "Encontre endereços por lugar, com coordenadas e referência de 2022. Não certifica CEP vigente.",
        "hierarchy": "UF → município → bairro/localidade → rua → endereços",
        "url": "https://api.pontofato.com/enderecos/",
        "formats": {
          "html": "https://api.pontofato.com/enderecos/",
          "json": "https://api.pontofato.com/enderecos/index.json",
          "md": "https://api.pontofato.com/enderecos/index.md",
          "okf": "https://api.pontofato.com/enderecos/index.okf.md"
        },
        "llms": "https://api.pontofato.com/enderecos/llms.txt",
        "openapi": "https://api.pontofato.com/enderecos/openapi.json",
        "mcp": "https://api.pontofato.com/enderecos/mcp",
        "okf": "https://api.pontofato.com/enderecos/okf/index.md",
        "access": "public-read-only",
        "pagination": {
          "max_items": 20,
          "next": "links.proximo"
        },
        "updates": "manual"
      },
      {
        "id": "editais",
        "produto": "https://editalmd.com",
        "caminho": "/licitacoes",
        "title": "Editais e compras públicas",
        "description": "Encontre compras públicas por lugar e período. Consulte documentos e opções de leitura no EditalMD.",
        "hierarchy": "Modalidade → UF → ano → mês → dia → município → compras",
        "url": "https://api.editalmd.com/licitacoes/",
        "formats": {
          "html": "https://api.editalmd.com/licitacoes/",
          "json": "https://api.editalmd.com/licitacoes/index.json",
          "md": "https://api.editalmd.com/licitacoes/index.md",
          "okf": "https://api.editalmd.com/licitacoes/index.okf.md"
        },
        "llms": "https://api.editalmd.com/licitacoes/llms.txt",
        "openapi": "https://api.editalmd.com/licitacoes/openapi.json",
        "mcp": "https://api.editalmd.com/licitacoes/mcp",
        "okf": "https://api.editalmd.com/licitacoes/okf/index.md",
        "access": "public-read-only",
        "pagination": {
          "max_items": 20,
          "next": "links.proximo"
        },
        "updates": "manual"
      }
    ]
  },
  "conventions": {
    "format": "JSON; erros `{ ok:false, code, error }`.",
    "cache": "/api/cnpj/* cache 6h; /api/local e /api/contato nunca cache.",
    "contact_agent": "POST /api/contato sem captcha → x402 $0.10.",
    "parity": "Mexeu na UI/API → apidocs + skill + MCP + llms no mesmo PR."
  },
  "auth": {
    "credito": "Token de crédito em `Authorization: Bearer cred_…` (ou header `X-Credito`). Não é conta: é portador de saldo.",
    "none": "Público (algumas rotas de origem podem restringir por geo BR).",
    "session": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores.",
    "token": "Token de operador `METRICS_TOKEN` em `Authorization: Bearer`."
  },
  "endpoints": [
    {
      "method": "GET",
      "path": "/api/auth/bootstrap",
      "auth": "none",
      "grupo": "Conta",
      "summary": "Prepara o navegador para entrar na conta global.",
      "desc": "Define cookie HttpOnly restrito ao host. CSRF vinculado à sessão atual. Sem CORS.",
      "retorno": {
        "csrf": {
          "tipo": "string",
          "desc": "X-CSRF-Token"
        },
        "context": {
          "tipo": "string",
          "desc": "Opaque view context, also in X-MM-Context; not a credential / contexto opaco da vista, não é credencial."
        }
      },
      "erros": {
        "400": "invalid_request",
        "403": "invalid_origin / invalid_csrf",
        "503": "auth_unavailable: a sessão anterior é preservada / the previous session is preserved"
      },
      "returns": "{ csrf, context }",
      "url": "https://radar-cnpj.com/api/auth/bootstrap",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/account/profile",
      "auth": "session",
      "grupo": "Conta",
      "exemplo": "await fetch(\"$ORIGIN/api/account/profile\", {credentials: \"same-origin\"}).then(r => r.json());",
      "exemploLinguagem": "js",
      "summary": "Consulta seu perfil global.",
      "desc": "Lê preferências atuais da conta. Altere-as na página da conta; produtos não mantêm perfil autoritativo separado.",
      "retorno": {
        "_texto": "{profile:{name,locale,timeZone,theme,revision}}"
      },
      "erros": {
        "401": "invalid_session",
        "503": "auth_unavailable"
      },
      "returns": "{profile:{name,locale,timeZone,theme,revision}}",
      "url": "https://radar-cnpj.com/api/account/profile",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "GET",
      "path": "/api/account/avatar",
      "auth": "session",
      "grupo": "Conta",
      "exemplo": "await fetch(\"$ORIGIN/api/account/avatar\", {credentials: \"same-origin\"}).then(r => {if (!r.ok) throw new Error(\"HTTP \" + r.status); return r.blob();});",
      "exemploLinguagem": "js",
      "summary": "Consulta sua foto de perfil global.",
      "desc": "WebP privado de até 64 KiB, sem cache. Altere-o na conta. Não aceita ID de usuário ou URL de objeto.",
      "retorno": {
        "_texto": "image/webp; Cache-Control: no-store"
      },
      "erros": {
        "401": "invalid_session",
        "404": "not_found: no photo / sem foto",
        "503": "auth_unavailable"
      },
      "returns": "image/webp; Cache-Control: no-store",
      "url": "https://radar-cnpj.com/api/account/avatar",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "GET",
      "path": "/api/me",
      "auth": "session",
      "grupo": "Conta",
      "exemplo": "await fetch(\"$ORIGIN/api/me\", {credentials: \"same-origin\"}).then(r => r.json());",
      "exemploLinguagem": "js",
      "summary": "Lê a conta global atual neste produto.",
      "retorno": {
        "_texto": "{user:{identityId,sessionId,productId,audience,authTime,methods,mfaState}}"
      },
      "erros": {
        "401": "invalid_session",
        "503": "auth_unavailable"
      },
      "returns": "{user:{identityId,sessionId,productId,audience,authTime,methods,mfaState}}",
      "url": "https://radar-cnpj.com/api/me",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "POST",
      "path": "/api/auth/logout",
      "auth": "session",
      "grupo": "Conta",
      "exemplo": "// Execute no console da página do produto / Run in the product page console.\n(async () => {\n  const origin = \"$ORIGIN\";\n  const {csrf} = await fetch(origin + \"/api/auth/bootstrap\").then(r => r.json());\n  const r = await fetch(origin + \"/api/auth/logout\", {\n    method: \"POST\", credentials: \"same-origin\",\n    headers: {\"Content-Type\": \"application/json\", \"X-CSRF-Token\": csrf},\n    body: JSON.stringify({})\n  });\n  if (!r.ok) throw new Error(\"Auth HTTP \" + r.status);\n  return r.json();\n})();",
      "exemploLinguagem": "js",
      "summary": "Revoga esta sessão do produto.",
      "desc": "Exige bootstrap/CSRF deste navegador e sessão. As sessões de outros produtos permanecem ativas.",
      "retorno": {
        "ok": {
          "tipo": "bool",
          "desc": "true"
        }
      },
      "erros": {
        "400": "invalid_request",
        "403": "invalid_origin / invalid_csrf",
        "503": "auth_unavailable: a sessão anterior é preservada / the previous session is preserved"
      },
      "returns": "{ ok }",
      "url": "https://radar-cnpj.com/api/auth/logout",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "GET",
      "path": "/api/account/keys",
      "auth": "session",
      "grupo": "Conta",
      "summary": "Lista suas chaves de API neste produto.",
      "desc": "Nunca devolve a chave: nome, 4 últimos caracteres, organização, criação, último uso (por hora) e se ainda vale.",
      "retorno": {
        "keys": {
          "tipo": "object[]",
          "desc": "`id`, `name`, `organizationId`, `last4`, `createdAt`, `lastUsedAt`, `revokedAt`, `active` (false quando revogada ou parada por troca de senha / encerrar todos os acessos)."
        }
      },
      "erros": {
        "401": "invalid_session",
        "503": "auth_unavailable"
      },
      "exemplo": "await fetch(\"$ORIGIN/api/account/keys\", {credentials: \"same-origin\"}).then(r => r.json());",
      "exemploLinguagem": "js",
      "returns": "{ keys }",
      "url": "https://radar-cnpj.com/api/account/keys",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "POST",
      "path": "/api/account/keys/create",
      "auth": "session",
      "grupo": "Conta",
      "summary": "Cria uma chave de API para agentes e scripts.",
      "desc": "Exige entrada nos últimos 5 minutos; a de organização também exige segundo fator na sessão e o papel de dona/administradora com o produto ligado. No máximo 10 chaves vivas por conta e produto. A chave (`secret`) volta UMA vez.",
      "corpo": {
        "name": {
          "tipo": "string",
          "obrigatorio": true,
          "desc": "Até 60 caracteres."
        },
        "organizationId": {
          "tipo": "string",
          "nulo": true,
          "obrigatorio": true,
          "desc": "`null` para chave da conta."
        }
      },
      "body": {
        "name": "agent",
        "organizationId": null
      },
      "retorno": {
        "key": {
          "tipo": "object",
          "desc": "`id`, `name`, `organizationId`, `last4`, `createdAt`."
        },
        "secret": {
          "tipo": "string",
          "desc": "`mmk_…`, mostrada uma vez."
        }
      },
      "erros": {
        "400": "invalid_key_name / invalid_organization",
        "401": "invalid_session / reauth_required",
        "403": "invalid_origin / invalid_csrf / organization_forbidden / organization_mfa_required",
        "409": "key_limit_reached",
        "503": "auth_unavailable"
      },
      "exemplo": "(async () => {\n  const {csrf} = await fetch(\"$ORIGIN/api/auth/bootstrap\").then(r => r.json());\n  const r = await fetch(\"$ORIGIN/api/account/keys/create\", {method: \"POST\", credentials: \"same-origin\",\n    headers: {\"Content-Type\": \"application/json\", \"X-CSRF-Token\": csrf},\n    body: JSON.stringify({name: \"agent\", organizationId: null})});\n  return r.json();\n})();",
      "exemploLinguagem": "js",
      "returns": "{ key, secret }",
      "url": "https://radar-cnpj.com/api/account/keys/create",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "POST",
      "path": "/api/account/keys/revoke",
      "auth": "session",
      "grupo": "Conta",
      "summary": "Revoga uma das suas chaves de API.",
      "desc": "Para a chave na hora. Repetir não faz mal.",
      "corpo": {
        "id": {
          "tipo": "string",
          "obrigatorio": true,
          "desc": "O `id` da chave."
        }
      },
      "body": {
        "id": "…"
      },
      "retorno": {
        "ok": {
          "tipo": "bool",
          "desc": "true"
        }
      },
      "erros": {
        "400": "invalid_key_id",
        "401": "invalid_session",
        "403": "invalid_origin / invalid_csrf",
        "404": "key_not_found",
        "503": "auth_unavailable"
      },
      "exemplo": "(async () => {\n  const {csrf} = await fetch(\"$ORIGIN/api/auth/bootstrap\").then(r => r.json());\n  const r = await fetch(\"$ORIGIN/api/account/keys/revoke\", {method: \"POST\", credentials: \"same-origin\",\n    headers: {\"Content-Type\": \"application/json\", \"X-CSRF-Token\": csrf},\n    body: JSON.stringify({id: \"…\"})});\n  return r.json();\n})();",
      "exemploLinguagem": "js",
      "returns": "{ ok }",
      "url": "https://radar-cnpj.com/api/account/keys/revoke",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "GET",
      "path": "/okf/:arquivo",
      "auth": "none",
      "summary": "Bundle OKF (Open Knowledge Format v0.1): markdown com frontmatter para o agente ler o produto inteiro sem parsear HTML.",
      "grupo": "Descoberta",
      "params": {
        "arquivo": {
          "desc": "`index.md`, `sobre.md`, `api.md` ou `faq.md`.",
          "exemplo": "index.md"
        }
      },
      "retorno": {
        "_texto": "`text/markdown`. Comece por `/okf/index.md`, que lista o bundle."
      },
      "erros": {
        "404": "Arquivo fora do bundle."
      },
      "exemplo": "curl -s $ORIGIN/okf/index.md",
      "returns": "`text/markdown`. Comece por `/okf/index.md`, que lista o bundle.",
      "url": "https://radar-cnpj.com/okf/:arquivo",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/.well-known/:arquivo",
      "auth": "none",
      "summary": "Descoberta de máquina antes da home: `api-catalog` (RFC 9727, linkset com a API e o MCP), `security.txt` (RFC 9116), `x402` (manifesto de pagamento: rede, carteira e rotas que cobram), `agent-card.json` (identidade do agente: ferramentas MCP e portas de descoberta; também em `/agent.json`) e `mcp-registry-auth` (chave do registro oficial de MCP).",
      "grupo": "Descoberta",
      "params": {
        "arquivo": {
          "desc": "`api-catalog`, `security.txt`, `x402`, `agent-card.json`, `mcp-registry-auth` ou `apis.json`.",
          "exemplo": "api-catalog"
        }
      },
      "retorno": {
        "_texto": "`application/linkset+json` no api-catalog; `application/json` no x402, no agent-card.json e no apis.json; `text/plain` nos outros dois."
      },
      "erros": {
        "404": "Nome fora dos seis publicados."
      },
      "exemplo": "curl -s $ORIGIN/.well-known/api-catalog",
      "returns": "`application/linkset+json` no api-catalog; `application/json` no x402, no agent-card.json e no apis.json; `text/plain` nos outros dois.",
      "url": "https://radar-cnpj.com/.well-known/:arquivo",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/apis.json",
      "auth": "none",
      "summary": "APIs.json (apisjson.org, 0.19): o índice que o APIs.io colhe — a API, o MCP, OpenAPI, guia e bundle OKF num arquivo só. Também em `/.well-known/apis.json`.",
      "grupo": "Descoberta",
      "retorno": {
        "_texto": "`application/json` no formato APIs.json 0.19: `apis[]` com `baseURL`, `humanURL` e `properties[]`."
      },
      "exemplo": "curl -s $ORIGIN/apis.json",
      "returns": "`application/json` no formato APIs.json 0.19: `apis[]` com `baseURL`, `humanURL` e `properties[]`.",
      "url": "https://radar-cnpj.com/apis.json",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/agent.json",
      "auth": "none",
      "summary": "Cartão do agente: identidade, quem opera, documentação, o endpoint MCP e as ferramentas que ele serve. Mesmo documento de `/.well-known/agent-card.json`.",
      "grupo": "Descoberta",
      "retorno": {
        "_texto": "`application/json`: `name`, `provider`, `protocol` (`mcp`), `interfaces[]` e `skills[]`."
      },
      "exemplo": "curl -s $ORIGIN/agent.json",
      "returns": "`application/json`: `name`, `provider`, `protocol` (`mcp`), `interfaces[]` e `skills[]`.",
      "url": "https://radar-cnpj.com/agent.json",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/okf/:tipo/:id.md",
      "auth": "none",
      "summary": "O mesmo registro que a API responde, em markdown OKF: `cnpj` (Empresa por CNPJ, na base da Receita). Via de acesso para quem já tem o id, não catálogo.",
      "grupo": "Descoberta",
      "params": {
        "tipo": {
          "desc": "Um de: `cnpj`.",
          "exemplo": "cnpj"
        },
        "id": {
          "desc": "O id do registro, como a API o aceita.",
          "exemplo": "00000000000191"
        }
      },
      "retorno": {
        "_texto": "`text/markdown` com frontmatter OKF; `resource` aponta o JSON equivalente. Sem `.md` responde 301 para o canônico."
      },
      "erros": {
        "404": "Id fora da base, em markdown."
      },
      "exemplo": "curl -s $ORIGIN/okf/cnpj/00000000000191.md",
      "returns": "`text/markdown` com frontmatter OKF; `resource` aponta o JSON equivalente. Sem `.md` responde 301 para o canônico.",
      "url": "https://radar-cnpj.com/okf/:tipo/:id.md",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/",
      "auth": "none",
      "summary": "Índice da API, com operações, formatos, autenticação e limites.",
      "grupo": "Descoberta",
      "retorno": {
        "name": {
          "tipo": "string",
          "desc": "Nome do produto."
        },
        "description": {
          "tipo": "string",
          "desc": "O que o produto faz, em uma frase."
        },
        "build": {
          "tipo": "string",
          "desc": "Commit publicado."
        },
        "base_url": {
          "tipo": "string",
          "desc": "Origem em que esta API está servindo."
        },
        "origin_api": {
          "tipo": "string",
          "desc": "Endereço público da API de dados do produto."
        },
        "docs": {
          "tipo": "object",
          "desc": "Links para llms.txt, llms-full.txt, openapi.json, MCP e a UI."
        },
        "conventions": {
          "tipo": "object",
          "desc": "Formato de erro, CORS, x402 e a regra de paridade UI↔API."
        },
        "auth": {
          "tipo": "object",
          "desc": "Cada modo de autenticação e como obtê-lo."
        },
        "endpoints": {
          "tipo": "object[]",
          "desc": "Todo endpoint com método, caminho, auth, URL absoluta e o que devolve."
        },
        "quota": {
          "tipo": "object",
          "desc": "O que é grátis, o que custa e como pagar."
        },
        "mcp": {
          "tipo": "object",
          "desc": "Endereço e transporte do servidor MCP."
        },
        "mcp_tools": {
          "tipo": "string[]",
          "desc": "Nome de cada tool do MCP."
        },
        "quickstart": {
          "tipo": "string[]",
          "desc": "As chamadas que levam da ideia à lista de empresas."
        }
      },
      "returns": "{ name, description, build, base_url, origin_api, docs, conventions, auth, endpoints, quota, mcp, mcp_tools, quickstart }",
      "url": "https://radar-cnpj.com/api/",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/health",
      "auth": "none",
      "summary": "Disponibilidade e data de referência dos registros.",
      "grupo": "Descoberta",
      "desc": "`import.dump_date` informa a data de referência e `import.counts` traz as contagens disponíveis. A consulta não confirma mudanças em tempo real.",
      "retorno": "SaudeOrigem",
      "returns": "{ ok, service, db, import }",
      "url": "https://radar-cnpj.com/api/health",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/mcp",
      "auth": "none",
      "summary": "Servidor MCP por HTTP (Streamable HTTP, JSON-RPC 2.0) — pluga no cliente sem instalar nada.",
      "grupo": "Descoberta",
      "desc": "As tools são as operações deste mesmo catálogo; o MCP não tem backend próprio. `GET /mcp` devolve o cartão do servidor.",
      "retorno": {
        "_texto": "Resposta JSON-RPC 2.0 (`initialize`, `tools/list` ou `tools/call`)."
      },
      "notes": [
        "Credencial vai nos headers de sempre (X-Guest-Token, Authorization, X-PAYMENT) e é repassada à API.",
        "Cota estourada chega como 402 com accepts[] dentro do resultado da tool — pague e repita."
      ],
      "exemplo": "curl -s -XPOST $ORIGIN/mcp -H 'content-type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'",
      "returns": "Resposta JSON-RPC 2.0 (`initialize`, `tools/list` ou `tools/call`).",
      "url": "https://radar-cnpj.com/mcp",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/avaliar",
      "auth": "none",
      "summary": "Descreva uma atividade e um lugar para consultar as empresas registradas nesse recorte.",
      "grupo": "Avaliar ideia",
      "desc": "É o primeiro produto da home. Devolve o CNAE a que a ideia foi mapeada, quantas empresas ativas, abertas e baixadas existem no recorte, como elas se formalizam e uma leitura honesta disso. **Não inventa volume de busca** e não promete demanda: `ficha.limites` diz o que os números não dizem. Renda passiva isto não é.",
      "corpo": {
        "texto": {
          "tipo": "string",
          "desc": "A ideia em 3 a 400 caracteres.",
          "obrigatorio": true
        },
        "uf": {
          "tipo": "string",
          "desc": "Hint de estado; só entra se a IA não resolver o lugar sozinha.",
          "exemplo": "SP"
        },
        "municipio": {
          "tipo": "int",
          "desc": "Hint de município (código IBGE); mesma regra do `uf`."
        }
      },
      "body": {
        "texto": "padaria em Campinas",
        "uf": "SP",
        "municipio": 6291
      },
      "retorno": "Avaliacao",
      "erros": {
        "400": "Texto fora de 3–400 caracteres, ou corpo que não é JSON.",
        "405": "Só POST nesta rota."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/avaliar -H 'content-type: application/json' -d '{\"texto\":\"padaria em Campinas\"}'",
      "returns": "{ ok, texto, cnae, fonte_cnae, filtros, ficha{mapeou_cnae,oferta,formalizacao,leitura,limites,passivo} }",
      "url": "https://radar-cnpj.com/api/avaliar",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/cnpj/:cnpj",
      "auth": "none",
      "summary": "A ficha cadastral de uma empresa, pelos 14 dígitos do CNPJ, com o dado pessoal mascarado.",
      "grupo": "Consulta",
      "desc": "Nome de sócio pessoa física (`LUIS F. R. P.`), telefones e e-mail vêm mascarados, com `data.mascarado: true`; sócio empresa vem inteiro. O dado completo sai por `POST /api/revelar/:cnpj`. A resposta pode ser reutilizada por até 6 horas; confira a data de referência dos registros.",
      "params": {
        "cnpj": {
          "desc": "CNPJ com 14 dígitos, sem pontuação.",
          "exemplo": "00000000000191"
        }
      },
      "retorno": "FichaCnpj",
      "erros": {
        "400": "CNPJ que não tem 14 dígitos.",
        "404": "CNPJ não existe na base."
      },
      "exemplo": "curl -s $ORIGIN/api/cnpj/00000000000191",
      "returns": "{ ok, data }",
      "url": "https://radar-cnpj.com/api/cnpj/:cnpj",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/revelar/:cnpj",
      "auth": "credito",
      "summary": "Revela o dado pessoal da ficha — nomes dos sócios, telefones e e-mail sem máscara. Pago por empresa.",
      "grupo": "Consulta",
      "desc": "Custa US$ 0,10 por empresa: desconta do crédito pré-pago (`Authorization: Bearer cred_…`) ou paga só esta revelação com x402 (`X-PAYMENT`). O mesmo código de crédito revendo a mesma empresa no mesmo dia (horário de Brasília) não paga de novo; o x402 avulso cobra cada revelação. CNPJ inexistente ou consulta que falha não cobra nada. A resposta não vai para cache.",
      "params": {
        "cnpj": {
          "desc": "CNPJ com 14 dígitos, sem pontuação.",
          "exemplo": "00000000000191"
        }
      },
      "headers": {
        "authorization": {
          "tipo": "string",
          "desc": "`Bearer cred_…`, o token do crédito pré-pago. Sem ele (e sem `X-PAYMENT`), a resposta é o 402 do x402."
        },
        "x-payment": {
          "tipo": "string",
          "desc": "Pagamento x402 assinado (base64), para pagar só esta revelação."
        }
      },
      "retorno": "FichaRevelada",
      "erros": {
        "400": "CNPJ que não tem 14 dígitos.",
        "401": "Token de crédito desconhecido.",
        "402": "Sem pagamento ou com saldo insuficiente: o corpo traz `accepts[]` do x402 e como recarregar o crédito.",
        "404": "CNPJ não existe na base.",
        "502": "A consulta falhou; nada foi cobrado.",
        "503": "Revelação fora do ar; nada foi cobrado."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/revelar/00000000000191 -H \"Authorization: Bearer $CREDITO\"",
      "returns": "{ ok, data, cobranca }",
      "url": "https://radar-cnpj.com/api/revelar/:cnpj",
      "auth_detail": "Token de crédito em `Authorization: Bearer cred_…` (ou header `X-Credito`). Não é conta: é portador de saldo."
    },
    {
      "method": "GET",
      "path": "/api/busca",
      "auth": "none",
      "summary": "Busca empresas por termo e/ou filtros avançados, paginada.",
      "grupo": "Consulta",
      "desc": "Exige termo OU pelo menos um filtro — varrer 71 milhões de estabelecimentos sem recorte não é uma busca, é um dump.",
      "query": {
        "q": {
          "tipo": "string",
          "desc": "Termo de busca, entre 2 e 120 caracteres.",
          "exemplo": "padaria"
        },
        "f": {
          "tipo": "string",
          "desc": "Filtros avançados em JSON (CNAE, situação, porte, data de abertura).",
          "exemplo": "{\"uf\":\"SP\"}"
        },
        "tipo": {
          "tipo": "string",
          "desc": "Que campo o termo procura: `nome` (razão social, o padrão), `fantasia`, `socio`, `telefone` (com DDD, 10 ou 11 dígitos), `endereco` ou `cnae`.",
          "exemplo": "telefone"
        },
        "uf": {
          "tipo": "string",
          "desc": "Restringe a uma unidade da federação.",
          "exemplo": "SP"
        },
        "page": {
          "tipo": "int",
          "desc": "Página, começando em 0.",
          "padrao": 0
        },
        "pageSize": {
          "tipo": "int",
          "desc": "Resultados por página, de 1 a 50.",
          "padrao": 20
        }
      },
      "retorno": "PaginaDeBusca",
      "erros": {
        "400": "`busca_vazia` (sem termo nem filtro), `termo_invalido` (fora de 2–120) ou `filtros_invalidos`."
      },
      "exemplo": "curl -s '$ORIGIN/api/busca?q=padaria&uf=SP&pageSize=5'",
      "returns": "{ ok, page, pageSize, hasMore, results[{cnpj,cnpjFormatted,razaoSocial,nomeFantasia,situacao,uf,municipio,bairro,cnae}] }",
      "url": "https://radar-cnpj.com/api/busca",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/export",
      "auth": "none",
      "summary": "Exporta o resultado da busca em CSV ou JSON, com os mesmos filtros dela.",
      "grupo": "Consulta",
      "desc": "Duas formas na mesma rota. Com `format=json` a resposta é o envelope descrito abaixo — é o que um agente usa. Com `format=csv` (o padrão) vem o arquivo: content-type e content-disposition são repassados da origem, para o browser baixar direto do link. `capped` avisa quando o export bateu no teto e não trouxe tudo.",
      "query": {
        "q": {
          "tipo": "string",
          "desc": "Termo de busca, entre 2 e 120 caracteres.",
          "exemplo": "padaria"
        },
        "f": {
          "tipo": "string",
          "desc": "Filtros avançados em JSON (CNAE, situação, porte, data de abertura).",
          "exemplo": "{\"uf\":\"SP\"}"
        },
        "tipo": {
          "tipo": "string",
          "desc": "Que campo o termo procura: `nome` (razão social, o padrão), `fantasia`, `socio`, `telefone` (com DDD, 10 ou 11 dígitos), `endereco` ou `cnae`.",
          "exemplo": "telefone"
        },
        "uf": {
          "tipo": "string",
          "desc": "Restringe a uma unidade da federação.",
          "exemplo": "SP"
        },
        "format": {
          "tipo": "string",
          "desc": "Formato do arquivo.",
          "valores": [
            "csv",
            "json"
          ],
          "padrao": "csv"
        }
      },
      "retorno": "Export",
      "erros": {
        "400": "`formato_invalido`, ou os mesmos erros de `GET /api/busca`."
      },
      "exemplo": "curl -s '$ORIGIN/api/export?q=padaria&uf=SP&format=json'",
      "returns": "{ ok, count, capped, results[{cnpj,cnpjFormatted,razaoSocial,nomeFantasia,situacao,uf,municipio,bairro,cnae}] }",
      "url": "https://radar-cnpj.com/api/export",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/sugerir",
      "auth": "none",
      "summary": "Autocomplete de empresas e termos, para montar a lista enquanto a pessoa digita.",
      "grupo": "Consulta",
      "desc": "Não conta como visita nas métricas — senão o painel mediria tecla, não gente.",
      "query": {
        "q": {
          "tipo": "string",
          "desc": "O que já foi digitado.",
          "obrigatorio": true,
          "exemplo": "padar"
        },
        "limit": {
          "tipo": "int",
          "desc": "Quantas sugestões devolver, de 1 a 50.",
          "padrao": 10
        }
      },
      "retorno": "ListaSugestao",
      "erros": {
        "400": "`q` ausente ou curto demais."
      },
      "exemplo": "curl -s '$ORIGIN/api/sugerir?q=padar&limit=5'",
      "returns": "{ ok, results }",
      "url": "https://radar-cnpj.com/api/sugerir",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/ref",
      "auth": "none",
      "summary": "Vocabulários oficiais para montar seletor: CNAE, município e natureza jurídica.",
      "grupo": "Consulta",
      "desc": "Ou você busca por texto (`q`) ou resolve códigos que já tem (`codigos`) — `codigos` ganha quando os dois vêm.",
      "query": {
        "tipo": {
          "tipo": "string",
          "desc": "Qual vocabulário consultar.",
          "valores": [
            "cnae",
            "municipio",
            "natureza"
          ],
          "obrigatorio": true
        },
        "q": {
          "tipo": "string",
          "desc": "Texto a procurar no vocabulário, até 60 caracteres.",
          "exemplo": "padaria"
        },
        "codigos": {
          "tipo": "string",
          "desc": "Códigos separados por vírgula, para resolver os nomes deles.",
          "exemplo": "4721102,4712100"
        }
      },
      "retorno": "ListaReferencia",
      "erros": {
        "400": "`tipo` ausente ou fora da lista."
      },
      "exemplo": "curl -s '$ORIGIN/api/ref?tipo=cnae&q=padaria'",
      "returns": "{ ok, results[{codigo,descricao}] }",
      "url": "https://radar-cnpj.com/api/ref",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/ia",
      "auth": "none",
      "summary": "Transforma um texto livre nos filtros normalizados que a busca aceita.",
      "grupo": "IA",
      "desc": "Caminho síncrono: leva de 18 a 20 segundos. Quando estoura o tempo, use `POST /api/ia/jobs`.",
      "corpo": {
        "texto": {
          "tipo": "string",
          "desc": "A descrição em linguagem natural do que você procura.",
          "obrigatorio": true
        }
      },
      "body": {
        "texto": "padarias em SP com MEI"
      },
      "retorno": {
        "ok": {
          "tipo": "bool",
          "desc": "Sempre `true` quando a IA respondeu."
        },
        "filtros": {
          "tipo": "object[]",
          "desc": "Os filtros normalizados, prontos para virar o `f` de `GET /api/busca`."
        }
      },
      "erros": {
        "400": "Texto ausente ou fora do tamanho aceito.",
        "504": "O caminho síncrono estourou — enfileire em `POST /api/ia/jobs`."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/ia -H 'content-type: application/json' -d '{\"texto\":\"padarias em SP com MEI\"}'",
      "returns": "{ ok, filtros }",
      "url": "https://radar-cnpj.com/api/ia",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/ia/jobs",
      "auth": "none",
      "summary": "Enfileira a mesma tradução de texto para filtros, quando a síncrona não cabe no tempo.",
      "grupo": "IA",
      "corpo": {
        "texto": {
          "tipo": "string",
          "desc": "A descrição em linguagem natural do que você procura.",
          "obrigatorio": true
        }
      },
      "body": {
        "texto": "padarias em SP com MEI"
      },
      "retorno": {
        "job_id": {
          "tipo": "string",
          "desc": "ID do trabalho, para consultar em `GET /api/ia/jobs/:id`."
        },
        "eta": {
          "tipo": "int",
          "desc": "Estimativa de segundos até ficar pronto."
        }
      },
      "erros": {
        "400": "Texto ausente ou fora do tamanho aceito."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/ia/jobs -H 'content-type: application/json' -d '{\"texto\":\"padarias em SP com MEI\"}'",
      "returns": "{ job_id, eta }",
      "url": "https://radar-cnpj.com/api/ia/jobs",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/ia/jobs/:id",
      "auth": "none",
      "summary": "Consulta o trabalho de IA enfileirado; quando pronto, devolve os filtros.",
      "grupo": "IA",
      "params": {
        "id": {
          "desc": "ID do trabalho, vindo de `POST /api/ia/jobs`.",
          "exemplo": "9f3c2b1d7a4e58b0"
        }
      },
      "retorno": {
        "status": {
          "tipo": "string",
          "desc": "Estado do trabalho.",
          "valores": [
            "queued",
            "running",
            "done",
            "error"
          ]
        },
        "filtros": {
          "tipo": "object[]",
          "desc": "Os filtros normalizados; só quando `status` é `done`.",
          "opcional": true
        }
      },
      "erros": {
        "404": "Trabalho não existe ou já expirou."
      },
      "exemplo": "curl -s $ORIGIN/api/ia/jobs/JOB_ID",
      "returns": "{ status, filtros? }",
      "url": "https://radar-cnpj.com/api/ia/jobs/:id",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/local",
      "auth": "none",
      "summary": "Cidade e UF aproximadas de quem está chamando.",
      "grupo": "Geo",
      "desc": "Nunca é cacheada: cache aqui entregaria o lugar de outra pessoa.",
      "retorno": "Local",
      "returns": "{ ok, cidade, uf, cep, pais, fonte }",
      "url": "https://radar-cnpj.com/api/local",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/municipio-proximo",
      "auth": "none",
      "summary": "Município de um par de coordenadas, com o bairro quando disponível.",
      "grupo": "Geo",
      "desc": "Também nunca é cacheada. Coordenada ausente ou vazia NÃO vira zero — (0,0) é um lugar de verdade, no golfo da Guiné.",
      "query": {
        "lat": {
          "tipo": "number",
          "desc": "Latitude, entre -90 e 90.",
          "obrigatorio": true,
          "exemplo": "-23.55"
        },
        "lon": {
          "tipo": "number",
          "desc": "Longitude, entre -180 e 180.",
          "obrigatorio": true,
          "exemplo": "-46.63"
        }
      },
      "retorno": "MunicipioProximo",
      "erros": {
        "400": "`lat` ou `lon` ausentes ou fora da faixa.",
        "404": "`fora_do_brasil`: nenhum município brasileiro contém o ponto nem fica a até 50 km dele.",
        "503": "`sem_malha`: a base de contornos dos municípios está indisponível."
      },
      "exemplo": "curl -s '$ORIGIN/api/municipio-proximo?lat=-23.55&lon=-46.63'",
      "returns": "{ ok, municipio, bairro?, cep?, bairro_km? }",
      "url": "https://radar-cnpj.com/api/municipio-proximo",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/me/monitor/watches",
      "auth": "session",
      "summary": "Os CNPJs que você acompanha, com a cota aplicada (grátis + vagas compradas).",
      "grupo": "Monitoramento",
      "desc": "Quem confere a cota é a origem (`api.radar-cnpj.com`), dentro da transação; o Worker calcula quanto você tem (10 grátis + as vagas em vigor) e manda junto. Watch além da cota vem com `suspensa: true` e não gera e-mail.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "Agente: `Bearer mmk_…`, a chave de API da conta (criada na página da conta, Chaves de API) — a conta é a dona; ou `Bearer cred_…`, o token do crédito global (`POST /api/credito`) — a carteira é a dona. No navegador vale o cookie da conta; escrita leva `X-CSRF-Token`.",
          "obrigatorio": false
        }
      },
      "retorno": "Watches",
      "erros": {
        "401": "Sem conta (cookie ou chave de API) nem token de crédito válido: `nao_logado`; chave recusada: `invalid_api_key`.",
        "503": "A conta não respondeu agora."
      },
      "exemplo": "curl -s $ORIGIN/api/me/monitor/watches -H \"Authorization: Bearer $CREDITO\"",
      "returns": "{ ok, watches, quota, base, pagos, used, suspensas }",
      "url": "https://radar-cnpj.com/api/me/monitor/watches",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "POST",
      "path": "/api/me/monitor/watch",
      "auth": "session",
      "summary": "Passa a acompanhar um CNPJ. Os 10 primeiros são grátis; cada vaga a mais, US$ 0,50 por 30 dias.",
      "grupo": "Monitoramento",
      "desc": "Estourou a cota: **402 com `accepts[]`** (x402) — ou, com token de crédito, o débito direto do saldo. Pague e repita a mesma chamada com `X-PAYMENT`; a vaga fica no `direito` global e a watch entra.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "Agente: `Bearer mmk_…`, a chave de API da conta (criada na página da conta, Chaves de API) — a conta é a dona; ou `Bearer cred_…`, o token do crédito global (`POST /api/credito`) — a carteira é a dona. No navegador vale o cookie da conta; escrita leva `X-CSRF-Token`.",
          "obrigatorio": false
        }
      },
      "corpo": {
        "cnpj": {
          "tipo": "string",
          "desc": "CNPJ a acompanhar, 14 dígitos sem pontuação.",
          "obrigatorio": true
        }
      },
      "body": {
        "cnpj": "00000000000000"
      },
      "retorno": "Ok",
      "erros": {
        "400": "CNPJ que não tem 14 dígitos.",
        "401": "Sem conta (cookie ou chave de API) nem token de crédito válido: `nao_logado`; chave recusada: `invalid_api_key`.",
        "402": null,
        "403": "`invalid_origin` / `invalid_csrf`: escrita com o cookie da conta vinda de outra origem ou sem `X-CSRF-Token`.",
        "503": "A conta não respondeu agora."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/me/monitor/watch -H \"Authorization: Bearer $CREDITO\" -H 'content-type: application/json' -d '{\"cnpj\":\"00000000000191\"}'",
      "returns": "{ ok }",
      "url": "https://radar-cnpj.com/api/me/monitor/watch",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "DELETE",
      "path": "/api/me/monitor/watch/:cnpj",
      "auth": "session",
      "summary": "Para de acompanhar um CNPJ. A chave é o próprio CNPJ, não um id.",
      "grupo": "Monitoramento",
      "params": {
        "cnpj": {
          "desc": "CNPJ a deixar de acompanhar, 14 dígitos sem pontuação.",
          "exemplo": "00000000000191"
        }
      },
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "Agente: `Bearer mmk_…`, a chave de API da conta (criada na página da conta, Chaves de API) — a conta é a dona; ou `Bearer cred_…`, o token do crédito global (`POST /api/credito`) — a carteira é a dona. No navegador vale o cookie da conta; escrita leva `X-CSRF-Token`.",
          "obrigatorio": false
        }
      },
      "retorno": "Ok",
      "erros": {
        "401": "Sem conta (cookie ou chave de API) nem token de crédito válido: `nao_logado`; chave recusada: `invalid_api_key`.",
        "403": "`invalid_origin` / `invalid_csrf`: escrita com o cookie da conta vinda de outra origem ou sem `X-CSRF-Token`.",
        "404": "Este CNPJ não está sendo acompanhado por você."
      },
      "exemplo": "curl -s -XDELETE $ORIGIN/api/me/monitor/watch/00000000000191 -H \"Authorization: Bearer $CREDITO\"",
      "returns": "{ ok }",
      "url": "https://radar-cnpj.com/api/me/monitor/watch/:cnpj",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "GET",
      "path": "/api/me/monitor/alerts",
      "auth": "session",
      "summary": "Os alertas gerados para os CNPJs que você acompanha.",
      "grupo": "Monitoramento",
      "desc": "`retidos` conta os alertas de watches suspensas (fora da cota): voltam a aparecer quando a cota volta. Conta com e-mail verificado recebe os alertas também por e-mail; carteira de agente, só aqui.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "Agente: `Bearer mmk_…`, a chave de API da conta (criada na página da conta, Chaves de API) — a conta é a dona; ou `Bearer cred_…`, o token do crédito global (`POST /api/credito`) — a carteira é a dona. No navegador vale o cookie da conta; escrita leva `X-CSRF-Token`.",
          "obrigatorio": false
        }
      },
      "retorno": "Alertas",
      "erros": {
        "401": "Sem conta (cookie ou chave de API) nem token de crédito válido: `nao_logado`; chave recusada: `invalid_api_key`."
      },
      "exemplo": "curl -s $ORIGIN/api/me/monitor/alerts -H \"Authorization: Bearer $CREDITO\"",
      "returns": "{ ok, alerts, retidos }",
      "url": "https://radar-cnpj.com/api/me/monitor/alerts",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "GET",
      "path": "/api/monitor/changes/:cnpj",
      "auth": "session",
      "summary": "O histórico de alterações cadastrais de um CNPJ.",
      "grupo": "Monitoramento",
      "desc": "É o que o monitoramento observa: cada linha diz o que mudou, de que valor para qual, e quando. O nome de sócio sai mascarado.",
      "params": {
        "cnpj": {
          "desc": "CNPJ a consultar, 14 dígitos sem pontuação.",
          "exemplo": "00000000000191"
        }
      },
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "Agente: `Bearer mmk_…`, a chave de API da conta (criada na página da conta, Chaves de API) — a conta é a dona; ou `Bearer cred_…`, o token do crédito global (`POST /api/credito`) — a carteira é a dona. No navegador vale o cookie da conta; escrita leva `X-CSRF-Token`.",
          "obrigatorio": false
        }
      },
      "retorno": "HistoricoCnpj",
      "erros": {
        "401": "Sem conta (cookie ou chave de API) nem token de crédito válido: `nao_logado`; chave recusada: `invalid_api_key`.",
        "404": "CNPJ sem histórico ou fora da base."
      },
      "exemplo": "curl -s $ORIGIN/api/monitor/changes/00000000000191 -H \"Authorization: Bearer $CREDITO\"",
      "returns": "{ ok, cnpj, cnpjFormatted, changes }",
      "url": "https://radar-cnpj.com/api/monitor/changes/:cnpj",
      "auth_detail": "A conta global: Sessão global em cookie HttpOnly do produto; escritas exigem Origin exato e X-CSRF-Token. O monitoramento (`/api/me/monitor/*`, `/api/monitor/changes/:cnpj`) é da conta; agente sem conta usa o crédito global em `Authorization: Bearer cred_…` (ou `X-Credito`), e a carteira vira a dona dos monitores."
    },
    {
      "method": "POST",
      "path": "/api/contato",
      "auth": "none",
      "summary": "Fala com o suporte: humano resolve Turnstile, agente paga $0.10 em x402.",
      "grupo": "Contato",
      "desc": "O primeiro envio de agente é livre; depois o backoff é 60s dobrando até o teto de 1 hora, informado em `Retry-After`. `POST /api/contact` é o mesmo recurso com os campos em inglês.",
      "corpo": {
        "nome": {
          "tipo": "string",
          "desc": "Como chamar quem escreveu.",
          "obrigatorio": true
        },
        "email": {
          "tipo": "string",
          "desc": "Para onde responder.",
          "obrigatorio": true
        },
        "mensagem": {
          "tipo": "string",
          "desc": "O que você quer dizer.",
          "obrigatorio": true
        },
        "aberto_em": {
          "tipo": "int",
          "desc": "Momento em que o formulário abriu; é anti-robô do caminho humano."
        },
        "turnstile": {
          "tipo": "string",
          "desc": "Resposta do Turnstile; presente só no caminho humano."
        }
      },
      "body": {
        "nome": "…",
        "email": "a@example.com",
        "mensagem": "…",
        "aberto_em": 0,
        "turnstile": "(humano)"
      },
      "retorno": "Ok",
      "erros": {
        "400": "Campo obrigatório faltando.",
        "402": null,
        "429": "Backoff de agente: espere o `Retry-After`."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/contato -H \"X-PAYMENT: $PAGAMENTO\" -H 'content-type: application/json' -d '{\"nome\":\"Agente\",\"email\":\"a@example.com\",\"mensagem\":\"Olá\"}'",
      "returns": "{ ok }",
      "url": "https://radar-cnpj.com/api/contato",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/contact",
      "auth": "none",
      "summary": "O mesmo contato de `/api/contato`, com os nomes de campo em inglês.",
      "grupo": "Contato",
      "desc": "Existe porque agente que chegou pelo `llms.txt` de outro produto do mesmo dono já sabe mandar `name`/`email`/`message`. Mesmo backoff, mesmo preço.",
      "corpo": {
        "name": {
          "tipo": "string",
          "desc": "Como chamar quem escreveu.",
          "obrigatorio": true
        },
        "email": {
          "tipo": "string",
          "desc": "Para onde responder.",
          "obrigatorio": true
        },
        "message": {
          "tipo": "string",
          "desc": "O que você quer dizer.",
          "obrigatorio": true
        },
        "form_ts": {
          "tipo": "int",
          "desc": "Momento em que o formulário abriu; é anti-robô do caminho humano."
        },
        "tipo": {
          "tipo": "string",
          "desc": "Proposta: `patrocinio`, `parceria` ou `anuncio`. Liga os campos abaixo."
        },
        "empresa": {
          "tipo": "string",
          "desc": "Quem propõe, quando é empresa."
        },
        "site": {
          "tipo": "string",
          "desc": "Site de quem propõe."
        },
        "orcamento": {
          "tipo": "string",
          "desc": "`ate_100`, `100_500`, `500_2000`, `2000_mais` ou `a_combinar`."
        },
        "espaco": {
          "tipo": "string[]",
          "desc": "Ids de placement de `GET /api/partners`, até 6."
        },
        "duracao": {
          "tipo": "string",
          "desc": "Dias de exposição: `30`, `90` ou `365`."
        },
        "pagamento": {
          "tipo": "string",
          "desc": "`usdc`, `deposito` ou `a_combinar`."
        }
      },
      "body": {
        "name": "…",
        "email": "…",
        "message": "…"
      },
      "retorno": "Ok",
      "erros": {
        "400": "Campo obrigatório faltando.",
        "402": null,
        "429": "Backoff de agente: espere o `Retry-After`."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/contact -H \"X-PAYMENT: $PAGAMENTO\" -H 'content-type: application/json' -d '{\"name\":\"Agente\",\"email\":\"a@example.com\",\"message\":\"Olá\"}'",
      "returns": "{ ok }",
      "url": "https://radar-cnpj.com/api/contact",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/erro-cliente",
      "auth": "none",
      "summary": "Relato de erro do navegador, enviado pela própria interface. Agente não precisa chamar.",
      "grupo": "Operação",
      "desc": "A interface relata sozinha erro de JS, promessa rejeitada, script/CSS que não carregou e bloqueio de CSP — uma vez por sessão — e o app relata falha tratada por `window.mmErro.relata`. O servidor valida o envelope, redige credencial, e-mail e telefone, junta repetições da mesma falha por minuto e registra um evento operacional; nada é gravado em banco. Não guarda IP, cookie, query nem o User-Agent inteiro. Responde 204 sempre, inclusive para relato inválido.",
      "corpo": {
        "code": {
          "tipo": "string",
          "desc": "Código da falha, `UI-` + letras/dígitos (`UI-JS-001` erro global, `UI-PROMESSA-001`, `UI-RECURSO-001`, `UI-CSP-001`, `UI-APP-001` relato do app).",
          "obrigatorio": true
        },
        "phase": {
          "tipo": "string",
          "desc": "Fase em que quebrou, minúsculas: `global`, `promessa`, `script`, `carregar_lista`…",
          "obrigatorio": true
        },
        "path": {
          "tipo": "string",
          "desc": "Caminho da página aberta, sem query."
        },
        "message": {
          "tipo": "string",
          "desc": "Mensagem do erro, até 2000 caracteres."
        },
        "stack": {
          "tipo": "string",
          "desc": "Stack trace, até 12000 caracteres."
        },
        "source": {
          "tipo": "string",
          "desc": "Script de origem; só o caminho é guardado."
        },
        "line": {
          "tipo": "int",
          "desc": "Linha no script de origem."
        },
        "column": {
          "tipo": "int",
          "desc": "Coluna no script de origem."
        },
        "visivel": {
          "tipo": "bool",
          "desc": "Se a aba estava visível quando quebrou."
        }
      },
      "body": {
        "code": "UI-APP-001",
        "phase": "carregar_lista",
        "path": "/",
        "message": "lista 500"
      },
      "retorno": {
        "_texto": "204 sem corpo, sempre — relato inválido, repetido ou acima do teto também recebe 204."
      },
      "exemplo": "curl -s -XPOST $ORIGIN/api/erro-cliente -H 'content-type: application/json' -d '{\"code\":\"UI-APP-001\",\"phase\":\"carregar_lista\",\"path\":\"/\",\"message\":\"lista 500\"}'",
      "returns": "204 sem corpo, sempre — relato inválido, repetido ou acima do teto também recebe 204.",
      "url": "https://radar-cnpj.com/api/erro-cliente",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/pagamento/aberto",
      "auth": "none",
      "statusOk": 202,
      "summary": "A interface relata que exibiu uma cobrança. Agentes não devem chamar.",
      "grupo": "Operação",
      "desc": "Relato sem corpo, da mesma origem, enviado automaticamente quando uma cobrança fica visível. Não inicia pagamento, não concede acesso e não recebe identidade ou credencial. Não grava banco por relato. Conta eventos, não pessoas únicas. O painel privado do operador separa pedidos de pagamento da API e aberturas da interface por dia UTC; os dois números podem se sobrepor.",
      "headers": {
        "Origin": {
          "tipo": "string",
          "desc": "A origem da página, idêntica à desta rota.",
          "obrigatorio": true
        },
        "Sec-Fetch-Site": {
          "tipo": "string",
          "desc": "`same-origin`, definido pelo navegador.",
          "obrigatorio": true
        },
        "X-MM-Payment-View": {
          "tipo": "string",
          "desc": "`1`, definido pelo componente comum.",
          "obrigatorio": true
        }
      },
      "retorno": {
        "_texto": "202 sem corpo se aceito; 204 se ignorado. Sempre no-store."
      },
      "returns": "202 sem corpo se aceito; 204 se ignorado. Sempre no-store.",
      "url": "https://radar-cnpj.com/api/pagamento/aberto",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/vitrine",
      "auth": "none",
      "grupo": "Números públicos",
      "summary": "Os números públicos do produto: tráfego, agentes, uso e confiabilidade, sem dinheiro.",
      "desc": "Projeção publicada de hora em hora pelo coletor da casa, arredondada a dois dígitos significativos; `null` é medição ausente, nunca zero. Cache de 15 minutos com ETag (`If-None-Match` → 304). Não há como enviar números por esta rota: a publicação é do coletor, com token próprio.",
      "retorno": {
        "v": {
          "tipo": "int",
          "desc": "Versão do contrato (1)."
        },
        "produto": {
          "tipo": "string",
          "desc": "Id do produto."
        },
        "publicado": {
          "tipo": "bool",
          "desc": "`false` antes da primeira publicação do coletor; aí só estas cinco chaves vêm."
        },
        "atualizado_em": {
          "tipo": "string",
          "desc": "Quando o coletor publicou (ISO 8601).",
          "nulo": true
        },
        "stale": {
          "tipo": "bool",
          "desc": "`true` quando a projeção tem mais de 26 h."
        },
        "nome": {
          "tipo": "string",
          "desc": "Nome do produto.",
          "opcional": true
        },
        "desde": {
          "tipo": "string",
          "desc": "Dia a partir do qual a série vale.",
          "nulo": true,
          "opcional": true
        },
        "fuso": {
          "tipo": "string",
          "desc": "Fuso dos dias (`UTC`).",
          "opcional": true
        },
        "hoje": {
          "tipo": "object",
          "desc": "O dia de hoje: páginas por classe (pessoa, IA, bot), chamadas de API por classe, leituras das superfícies de máquina e uso do produto.",
          "opcional": true
        },
        "dias": {
          "tipo": "object[]",
          "desc": "Até 31 dias, o mais antigo primeiro: `dia`, `paginas`, `api`, `api_ia`, `maquina`, `visitantes`, `uso`.",
          "opcional": true
        },
        "janelas": {
          "tipo": "object",
          "desc": "Somas de 7 e 30 dias (`d7`, `d30`).",
          "opcional": true
        },
        "visitantes": {
          "tipo": "object",
          "desc": "Visitantes únicos na borda em 7 dias.",
          "opcional": true
        },
        "pessoas": {
          "tipo": "object",
          "desc": "GA4 quando há: usuários, sessões, países, aparelhos e quem chegou de IA.",
          "nulo": true,
          "opcional": true
        },
        "agentes": {
          "tipo": "object",
          "desc": "Os agentes de IA e os bots que mais leem, 7 dias.",
          "opcional": true
        },
        "superficies": {
          "tipo": "object",
          "desc": "Leituras de OKF, llms, well-known, OpenAPI e MCP em 7 dias.",
          "opcional": true
        },
        "mcp": {
          "tipo": "object",
          "desc": "Chamadas MCP em 7 dias.",
          "opcional": true
        },
        "uso": {
          "tipo": "object",
          "desc": "Uso real do produto por recurso: rótulo, hoje, 7 e 30 dias.",
          "opcional": true
        },
        "contas": {
          "tipo": "object",
          "desc": "Usuários e convidados.",
          "nulo": true,
          "opcional": true
        },
        "confiabilidade": {
          "tipo": "object",
          "desc": "Percentual de pedidos sem 5xx em 7 dias e o build no ar.",
          "opcional": true
        },
        "catalogo": {
          "tipo": "object",
          "desc": "Tamanho do acervo, quando o produto tem um.",
          "nulo": true,
          "opcional": true
        },
        "apoio": {
          "tipo": "object",
          "desc": "Impressões e cliques por patrocinador, quando houver.",
          "opcional": true
        }
      },
      "exemplo": "curl -s $ORIGIN/api/vitrine",
      "returns": "{ v, produto, publicado, atualizado_em, stale, nome?, desde?, fuso?, hoje?, dias?, janelas?, visitantes?, pessoas?, agentes?, superficies?, mcp?, uso?, contas?, confiabilidade?, catalogo?, apoio? }",
      "url": "https://radar-cnpj.com/api/vitrine",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/vitrine/operador",
      "auth": "none",
      "grupo": "Números públicos",
      "summary": "O documento completo do produto no painel do operador — só com o token do operador.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "`Bearer <METRICS_TOKEN>` — a classe operador.",
          "obrigatorio": true
        }
      },
      "retorno": {
        "produto": {
          "tipo": "string",
          "desc": "Id do produto."
        },
        "atualizado_em": {
          "tipo": "string",
          "desc": "Quando o coletor publicou.",
          "nulo": true
        },
        "operador": {
          "tipo": "object",
          "desc": "O documento completo do coletor, com o que a projeção pública não carrega.",
          "nulo": true
        }
      },
      "erros": {
        "401": "Sem token, token errado ou token de outra classe.",
        "503": "Worker sem `METRICS_TOKEN` ou sem o control plane."
      },
      "exemplo": "curl -s $ORIGIN/api/vitrine/operador -H \"Authorization: Bearer $METRICS_TOKEN\"",
      "returns": "{ produto, atualizado_em, operador }",
      "url": "https://radar-cnpj.com/api/vitrine/operador",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/vitrine/painel",
      "auth": "none",
      "grupo": "Números públicos",
      "summary": "O painel da casa inteira, na forma que o gm lê — só com o token do operador.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "`Bearer <METRICS_TOKEN>` — a classe operador.",
          "obrigatorio": true
        }
      },
      "retorno": {
        "apps": {
          "tipo": "object[]",
          "desc": "Um documento do operador por produto, em ordem de id."
        },
        "updated": {
          "tipo": "string",
          "desc": "Quando o coletor fechou a rodada.",
          "opcional": true
        },
        "totals": {
          "tipo": "object",
          "desc": "Os totais da casa.",
          "opcional": true
        }
      },
      "erros": {
        "401": "Sem token, token errado ou token de outra classe.",
        "503": "Worker sem `METRICS_TOKEN` ou sem o control plane."
      },
      "exemplo": "curl -s $ORIGIN/api/vitrine/painel -H \"Authorization: Bearer $METRICS_TOKEN\"",
      "returns": "{ apps, updated?, totals? }",
      "url": "https://radar-cnpj.com/api/vitrine/painel",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/vitrine/cursores",
      "auth": "none",
      "grupo": "Números públicos",
      "summary": "O cursor de erro resolvido por produto (`borda`, `cli`) — só com o token do operador.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "`Bearer <METRICS_TOKEN>` — a classe operador.",
          "obrigatorio": true
        }
      },
      "retorno": {
        "_texto": "JSON: `{ [produto]: { borda?: ISO, cli?: ISO } }`; vazio é `{}`."
      },
      "erros": {
        "401": "Sem token, token errado ou token de outra classe.",
        "503": "Worker sem `METRICS_TOKEN` ou sem o control plane."
      },
      "exemplo": "curl -s $ORIGIN/api/vitrine/cursores -H \"Authorization: Bearer $METRICS_TOKEN\"",
      "returns": "JSON: `{ [produto]: { borda?: ISO, cli?: ISO } }`; vazio é `{}`.",
      "url": "https://radar-cnpj.com/api/vitrine/cursores",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/partners",
      "auth": "none",
      "grupo": "Parceria",
      "summary": "Parceria, patrocínio e anúncio: os espaços do produto com preço sugerido, os números públicos ao lado e como propor.",
      "desc": "Informação sob consulta, sem ativação: espaços do catálogo da casa com preço em USD por 30 dias (90 e 365 dias com desconto), patrocinadores em vigor, recorte de `/api/vitrine`, carteira da casa (USDC na Base) e o caminho de contato — depósito, PIX ou fatura são combinados na resposta. Cache de 1 hora.",
      "retorno": {
        "status": {
          "tipo": "string",
          "desc": "`sob_consulta`: informação e proposta, sem ativação nem cobrança."
        },
        "produto": {
          "tipo": "string",
          "desc": "Nome do produto."
        },
        "idioma": {
          "tipo": "string",
          "desc": "Idioma dos textos (o do produto)."
        },
        "titulo": {
          "tipo": "string",
          "desc": "Título da oferta."
        },
        "descricao": {
          "tipo": "string",
          "desc": "Uma frase sobre a oferta."
        },
        "publico": {
          "tipo": "string",
          "desc": "Quem usa o produto — o público que o patrocinador alcança."
        },
        "modalidades": {
          "tipo": "object[]",
          "desc": "`{ id, nome }`: patrocinio, parceria, anuncio."
        },
        "placements": {
          "tipo": "object[]",
          "desc": "Os espaços do produto: `id`, `nome`, `onde`, `formato`, `exclusivo`, `medicao`, `price_usd_30d` (sugestão; `null` é sob consulta), `exposure[{ dias, price_usd }]` para 30, 90 e 365 dias, `disponivel`."
        },
        "house_bundle": {
          "tipo": "object",
          "desc": "O pacote da casa: rodapé e menção para agentes nos dez produtos, com desconto."
        },
        "parcerias": {
          "tipo": "string[]",
          "desc": "Ideias de parceria que o produto aceita discutir."
        },
        "current_sponsors": {
          "tipo": "object[]",
          "desc": "Patrocinadores em vigor: `id`, `nome`, `url`, `frase`, `espacos`, `ate`."
        },
        "stats": {
          "tipo": "object",
          "desc": "Recorte dos números públicos (`hoje`, `janelas`, `agentes`, `confiabilidade`) e o `link` para `/api/vitrine`; `publicado: false` antes da primeira publicação."
        },
        "payment": {
          "tipo": "object",
          "desc": "Como pagar: `rede`, `chain_id`, `ativo`, `pay_to`, `eip681` (a carteira da casa, quando declarada), `alternativas` e a `nota` — depósito, PIX ou fatura pela resposta."
        },
        "contact": {
          "tipo": "object",
          "desc": "`email`, `form_url`, `api_url` (`POST /api/contact` onde há handler), `campos` (os obrigatórios), `campos_proposta` (os opcionais da proposta, com os valores aceitos de cada um), `price_agent_usd`, `message_template`, `instructions`."
        },
        "politica": {
          "tipo": "object",
          "desc": "Rótulo do espaço, setores recusados, pagamento adiantado, prazos."
        },
        "_links": {
          "tipo": "object",
          "desc": "`self`, `stats`, `page` (`null` até a página existir), `contact`, `casa` (o mesmo caminho nos dez produtos)."
        }
      },
      "exemplo": "curl -s $ORIGIN/api/partners",
      "returns": "{ status, produto, idioma, titulo, descricao, publico, modalidades, placements, house_bundle, parcerias, current_sponsors, stats, payment, contact, politica, _links }",
      "url": "https://radar-cnpj.com/api/partners",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/metrics",
      "auth": "none",
      "summary": "Métricas operacionais: sem token, visitas de hoje e uso; com o token do operador, a série de 7 dias.",
      "grupo": "Contato",
      "desc": "Conta visitantes distintos e **não** conta autocomplete — senão o painel mediria tecla, não gente. Sem `Authorization` devolve só `app`, `today_visits` e `usage`, com 5 min de cache na borda — é o que a linha de estado do rodapé lê, como nos outros produtos. Com `Bearer METRICS_TOKEN`, a resposta completa da origem (`days`), sem cache.",
      "headers": {
        "Authorization": {
          "tipo": "string",
          "desc": "`Bearer <METRICS_TOKEN>`, só para a série completa do operador.",
          "obrigatorio": false
        }
      },
      "retorno": "Metricas",
      "erros": {
        "401": "Token do operador errado.",
        "503": "Sem os secrets configurados no ambiente."
      },
      "exemplo": "curl -s $ORIGIN/api/metrics -H \"Authorization: Bearer $METRICS_TOKEN\"",
      "returns": "{ app, today_visits, days?, usage }",
      "url": "https://radar-cnpj.com/api/metrics",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "POST",
      "path": "/api/credito",
      "auth": "none",
      "summary": "Recarrega crédito pré-pago: paga uma vez com x402 e recebe o token que desconta em qualquer API da casa.",
      "grupo": "Crédito",
      "query": {
        "usd": {
          "tipo": "int",
          "desc": "Pacote: 1, 5, 10 ou 25 dólares.",
          "obrigatorio": true
        }
      },
      "retorno": {
        "token": {
          "tipo": "string",
          "desc": "Token portador do saldo (`cred_…`). Mostrado UMA vez — não há como recuperá-lo."
        },
        "saldo_usd": {
          "tipo": "string",
          "desc": "Saldo creditado."
        },
        "guarde": {
          "tipo": "string",
          "desc": "Aviso de que o token é o portador do crédito."
        },
        "usar": {
          "tipo": "string",
          "desc": "Como apresentar o token nas rotas pagas."
        },
        "saldo_em": {
          "tipo": "string",
          "desc": "Onde consultar saldo e extrato."
        }
      },
      "erros": {
        "400": "Pacote fora da lista (1, 5, 10 ou 25).",
        "402": "Sem pagamento — o corpo traz `accepts[]` do x402."
      },
      "exemplo": "curl -s -XPOST '$ORIGIN/api/credito?usd=10'",
      "returns": "{ token, saldo_usd, guarde, usar, saldo_em }",
      "url": "https://radar-cnpj.com/api/credito",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/credito",
      "auth": "credito",
      "summary": "Saldo e extrato do crédito — as últimas movimentações, sem devolver o token.",
      "grupo": "Crédito",
      "retorno": {
        "saldo_micros": {
          "tipo": "int",
          "desc": "Saldo em micro-dólares (1e-6 USD)."
        },
        "saldo_usd": {
          "tipo": "string",
          "desc": "Saldo formatado."
        },
        "criado_em": {
          "tipo": "string",
          "desc": "Quando o crédito foi aberto."
        },
        "movimentos": {
          "tipo": "object[]",
          "desc": "Entradas e saídas recentes, com produto e recurso."
        }
      },
      "erros": {
        "401": "Sem token ou token desconhecido."
      },
      "exemplo": "curl -s $ORIGIN/api/credito -H 'Authorization: Bearer cred_…'",
      "returns": "{ saldo_micros, saldo_usd, criado_em, movimentos }",
      "url": "https://radar-cnpj.com/api/credito",
      "auth_detail": "Token de crédito em `Authorization: Bearer cred_…` (ou header `X-Credito`). Não é conta: é portador de saldo."
    },
    {
      "path": "/api/acesso",
      "auth": "none",
      "grupo": "API access",
      "retorno": "ApiAccess",
      "method": "GET",
      "summary": "Discover the monthly data package or inspect a private purchase.",
      "headers": {
        "X-API-Pass": {
          "tipo": "string",
          "desc": "Private pass: api_<32 random hex>_<64 random hex>. Save before buying."
        }
      },
      "erros": {
        "400": "Invalid pass.",
        "404": "Unknown purchase or wrong owner.",
        "503": "Purchases disabled."
      },
      "exemplo": "curl -s $ORIGIN/api/acesso",
      "returns": "{ offer{id,price_usd,credits,days,auto_renew,unit,products,purchase,method,status,header,payment_methods,instructions,generate_pass,client,guide,workflow,evaluation}, enabled?, id?, status?, granted_credits?, expires_at?, receipt?, via?, message? }",
      "url": "https://radar-cnpj.com/api/acesso",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "path": "/api/acesso",
      "auth": "none",
      "grupo": "API access",
      "retorno": "ApiAccess",
      "method": "POST",
      "summary": "Buy 1000 basic data reads for US$1, valid for 30 days.",
      "desc": "Same pass in retries recovers the same purchase. No automatic renewal. OCR, AI, documents and delivery keep their own tariffs. Send X-API-Pass on eligible data reads; remaining credits come in X-API-Credits-Remaining.",
      "headers": {
        "X-API-Pass": {
          "tipo": "string",
          "desc": "Private pass: api_<32 random hex>_<64 random hex>. Save before buying.",
          "obrigatorio": true
        },
        "X-Credito": {
          "tipo": "string",
          "desc": "Existing prepaid credit token; alternative to x402."
        },
        "Authorization": {
          "tipo": "string",
          "desc": "Bearer cred_… alternative to X-Credito."
        },
        "X-PAYMENT": {
          "tipo": "string",
          "desc": "Signed x402 authorization from the 402 quote, maximum 16 KiB."
        },
        "PAYMENT-SIGNATURE": {
          "tipo": "string",
          "desc": "Alternative name for X-PAYMENT."
        },
        "X-API-Transaction": {
          "tipo": "string",
          "desc": "Confirmed Base transaction hash for reconciliation with the original pass and signed payment. Never creates another charge."
        }
      },
      "erros": {
        "400": "Missing or invalid pass/payment.",
        "401": "Invalid prepaid credit.",
        "402": "Payment required: x402 accepts[] and prepaid-credit instructions.",
        "409": "Payment pending; retain the same pass and do not pay again.",
        "429": "Purchase attempt limit; respect Retry-After.",
        "503": "Payment unavailable or pending reconciliation."
      },
      "exemplo": "curl -s -X POST \"$ORIGIN/api/acesso\" -H \"X-API-Pass: $API_PASS\"",
      "returns": "{ offer{id,price_usd,credits,days,auto_renew,unit,products,purchase,method,status,header,payment_methods,instructions,generate_pass,client,guide,workflow,evaluation}, enabled?, id?, status?, granted_credits?, expires_at?, receipt?, via?, message? }",
      "url": "https://radar-cnpj.com/api/acesso",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/pricing",
      "auth": "none",
      "grupo": "Descoberta",
      "summary": "Preços vigentes e franquias gratuitas.",
      "retorno": {
        "product": {
          "tipo": "string",
          "desc": "Product name."
        },
        "quota": {
          "tipo": "PaymentQuota",
          "desc": "Public allowances and current list prices; not personal usage."
        },
        "pricing": {
          "tipo": "string",
          "desc": "Absolute URL of the current price list."
        },
        "billing": {
          "tipo": "string",
          "desc": "Absolute URL of payment discovery or the existing billing summary."
        },
        "api_index": {
          "tipo": "string",
          "desc": "Absolute URL of the API catalog."
        }
      },
      "erros": {
        "405": "Use GET ou HEAD."
      },
      "exemplo": "curl -s $ORIGIN/api/pricing",
      "returns": "{ product, quota{free,paid,how_to_pay,live,free_now?,trial?}, pricing, billing, api_index }",
      "url": "https://radar-cnpj.com/api/pricing",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    },
    {
      "method": "GET",
      "path": "/api/billing",
      "auth": "none",
      "grupo": "Descoberta",
      "summary": "Descoberta pública de pagamento e crédito pré-pago.",
      "retorno": {
        "product": {
          "tipo": "string",
          "desc": "Product name."
        },
        "quota": {
          "tipo": "PaymentQuota",
          "desc": "Public allowances and current list prices; not personal usage."
        },
        "pricing": {
          "tipo": "string",
          "desc": "Absolute URL of the current price list."
        },
        "billing": {
          "tipo": "string",
          "desc": "Absolute URL of payment discovery or the existing billing summary."
        },
        "api_index": {
          "tipo": "string",
          "desc": "Absolute URL of the API catalog."
        },
        "payment": {
          "tipo": "PaymentX402",
          "desc": "Public x402 configuration; pay_to=null means not configured."
        },
        "credit": {
          "tipo": "PaymentCredit",
          "desc": "Prepaid credit entry point. Never contains a balance or token."
        }
      },
      "erros": {
        "405": "Use GET ou HEAD."
      },
      "exemplo": "curl -s $ORIGIN/api/billing",
      "returns": "{ product, quota{free,paid,how_to_pay,live,free_now?,trial?}, pricing, billing, api_index, payment{provider,mode,network,chain_id,pay_to,homolog,dev,dev_gate,gratis?,facilitator,asset,asset_address,faucet,wallets}, credit{url,header} }",
      "url": "https://radar-cnpj.com/api/billing",
      "auth_detail": "Público (algumas rotas de origem podem restringir por geo BR)."
    }
  ],
  "quota": {
    "free": [
      {
        "o_que": "avaliar ideia (`POST /api/avaliar`)",
        "limite": "sem cota",
        "janela": null
      },
      {
        "o_que": "consulta e busca de CNPJ",
        "limite": "sem cota (cache de borda 6h)",
        "janela": null
      },
      {
        "o_que": "monitoramento de CNPJ",
        "limite": "10 watches por sessão (a cota vem da origem: `quota` em `GET /api/me/monitor/watches`)",
        "janela": null
      }
    ],
    "paid": [
      {
        "o_que": "1,000 basic reads across /empresas, /enderecos and /licitacoes, valid for 30 days; availability and purchase: GET/POST /api/acesso; no automatic renewal",
        "price_usd": 1
      },
      {
        "o_que": "watch de monitoramento além dos 10 da sessão, por 30 dias",
        "price_usd": 0.5
      },
      {
        "o_que": "contato de agente",
        "price_usd": 0.1
      }
    ],
    "how_to_pay": "Estourou a franquia → **402** com `accepts[]` (x402, USDC na Base). Pague e repita a mesma chamada com `X-PAYMENT`.",
    "live": "https://radar-cnpj.com/api/"
  },
  "mcp": {
    "endpoint": "https://radar-cnpj.com/mcp",
    "transport": "streamable-http",
    "tools": 17,
    "note": "Pluga direto no cliente MCP; sem instalar nada. Tools = as operações abaixo."
  },
  "mcp_tools": [
    "api_index",
    "health",
    "get_cnpj",
    "reveal_cnpj",
    "search",
    "suggest",
    "ref",
    "avaliar",
    "ia_filters",
    "local",
    "contact",
    "list_watches",
    "add_watch",
    "api_access",
    "api_access_buy",
    "pricing",
    "billing"
  ],
  "quickstart": [
    "curl -s -XPOST https://radar-cnpj.com/api/avaliar -H 'content-type: application/json' -d '{\"texto\":\"padaria em Campinas\"}'",
    "curl -s https://radar-cnpj.com/api/cnpj/14386974000160",
    "curl -s 'https://radar-cnpj.com/api/busca?q=padaria'"
  ]
}