{
  "openapi": "3.1.0",
  "info": {
    "title": "ExploriGen API",
    "version": "1.0.0",
    "summary": "API pública, somente leitura (read-only), da ExploriGen: páginas, busca, soluções, preços e leitura de prontidão técnica.",
    "description": "A versão vai no caminho (/api/v1/). Mudança incompatível nasce em /api/v2/ e a v1 continua no ar por pelo menos 90 dias depois do aviso, sinalizado pelos cabeçalhos Deprecation e Sunset (RFC 9745/8594). A API v1 é somente leitura (read-only): nenhuma operação cria, altera ou apaga dado. A política inteira, com as cotas (rate limit), está em https://explorigen.io/api/versioning.md. As operações da v1 são somente leitura; não há trabalho assíncrono nem endpoint de lote porque nenhuma delas altera estado. As duas que escrevem — o registro anônimo e a troca por access_token — aceitam `Idempotency-Key`: repetir com a mesma chave e o mesmo corpo devolve a mesma credencial, com `Idempotency-Replayed: true`. Cota (rate limit): toda resposta traz `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` e os campos estruturados `RateLimit-Policy` e `RateLimit`; acima da cota, 429 com `Retry-After`. A política de versionamento, depreciação e cota, por extenso, está em https://explorigen.io/api/versioning.md. Autenticação: registro anônimo (anonymous) em duas chamadas, sem conta — ver https://explorigen.io/auth.md. Sandbox (test mode) sem token em https://explorigen.io/api/v1/sandbox/. Erros sempre em JSON `{ error, error_description }`. Documentação para desenvolvedores (developers): https://explorigen.io/agentes.",
    "contact": {
      "name": "ExploriGen",
      "email": "contato@explorigen.io",
      "url": "https://explorigen.io/agentes"
    },
    "termsOfService": "https://explorigen.io/termos-de-uso"
  },
  "externalDocs": {
    "description": "Política de versionamento, depreciação e cota (versioning, deprecation and rate limit policy).",
    "url": "https://explorigen.io/api/versioning.md"
  },
  "servers": [
    {
      "url": "https://explorigen.io",
      "description": "Produção (production). Os caminhos abaixo são absolutos a partir desta origem."
    },
    {
      "url": "https://explorigen.io/api/v1/sandbox",
      "description": "Sandbox (test mode): mesmas rotas, dados fixos, sem token, nunca toca KV nem a ORA. As rotas do sandbox também estão listadas abaixo, completas, com a tag Sandbox — use-as; cada path item fixa o servidor de produção para não concatenar este prefixo a um caminho absoluto."
    }
  ],
  "tags": [
    {
      "name": "Público",
      "description": "Responde sem token."
    },
    {
      "name": "API v1",
      "description": "Bearer obrigatório (ver auth.md)."
    },
    {
      "name": "Sandbox",
      "description": "Mesmas rotas da v1, dados fixos, sem token."
    },
    {
      "name": "Autenticação de agentes",
      "description": "Registro anônimo e troca por access_token (perfil auth.md)."
    },
    {
      "name": "NLWeb",
      "description": "Busca em linguagem natural (/ask), lexical."
    },
    {
      "name": "Leitura de prontidão",
      "description": "O proxy do instrumento ora.ai que a página /diagnostico-de-visibilidade-cognitiva usa."
    }
  ],
  "paths": {
    "/api": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Público"
        ],
        "operationId": "indiceApi",
        "summary": "Índice público da API",
        "description": "Nome, versão, links de documentação, OpenAPI, auth.md, a política de versionamento e depreciação (/api/versioning.md) e o sandbox, a lista de endpoints com escopo, os escopos e a política de versão. Responde 200 sem token; é a porta pública. `/api/` (com barra) responde o mesmo.",
        "security": [],
        "responses": {
          "200": {
            "description": "Índice.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Indice"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "site.read"
            ]
          }
        ],
        "operationId": "indiceV1",
        "summary": "Índice da API v1 (autenticado)",
        "description": "O mesmo índice de GET /api, mais `registrado_como` (o registration_id do token) e `sandbox_token`. Sem bearer válido responde 401 com WWW-Authenticate.",
        "responses": {
          "200": {
            "description": "Índice.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndiceAutenticado"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/paginas": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "site.read"
            ]
          }
        ],
        "operationId": "listarPaginas",
        "summary": "Lista paginada das páginas públicas",
        "description": "Páginas do índice com rota, URL, título, descrição, seção e lastmod. Paginação por `limite` e `cursor`; `proximo` é o cursor da página seguinte, ausente na última.",
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "description": "Itens por página, 1..100 (padrão 50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Índice inicial em base64url, devolvido em `proximo` da página anterior.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página da lista.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaDePaginas"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/paginas/{rota}": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "site.read"
            ]
          }
        ],
        "operationId": "lerPagina",
        "summary": "Uma página em markdown",
        "description": "O markdown (espelho .md) de uma página do índice.",
        "parameters": [
          {
            "name": "rota",
            "in": "path",
            "required": true,
            "description": "Rota da página sem a barra inicial (ex.: `solucoes/seo-tecnico`). Só rotas presentes em /agentes/indice.json; fora dele, 404.",
            "schema": {
              "type": "string"
            },
            "allowReserved": true
          }
        ],
        "responses": {
          "200": {
            "description": "A página.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginaCompleta"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/busca": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "site.read"
            ]
          }
        ],
        "operationId": "buscar",
        "summary": "Busca lexical nas páginas",
        "description": "Busca por termos (keyword search) no título, descrição e texto das páginas; sem ranking semântico.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Termos de busca (obrigatório; vazio → 400).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limite",
            "in": "query",
            "description": "Resultados, 1..20 (padrão 8).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 8
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resultados.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultadoDeBusca"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/solucoes": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "site.read"
            ]
          }
        ],
        "operationId": "listarSolucoes",
        "summary": "Soluções e objetivos",
        "description": "As soluções do catálogo e as cinco portas por objetivo de negócio.",
        "responses": {
          "200": {
            "description": "Soluções e objetivos.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Solucoes"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/precos": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "site.read"
            ]
          }
        ],
        "operationId": "listarPrecos",
        "summary": "Preços públicos",
        "description": "Os produtos com preço público (o mesmo de /pricing.md); os demais serviços são sob proposta (custom pricing).",
        "responses": {
          "200": {
            "description": "Preços.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Precos"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/prontidao/{dominio}": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "API v1"
        ],
        "security": [
          {
            "agentAuth": [
              "prontidao.read"
            ]
          }
        ],
        "operationId": "lerProntidao",
        "summary": "Leitura de prontidão gravada de um domínio",
        "description": "Consulta a leitura de prontidão técnica gravada para o domínio (nota, grau, camadas, lacunas). Nunca mede: sem leitura, `estado` é `ausente`. Exige o escopo `prontidao.read`. Quando o instrumento está em pausa, 503 ou 429 com Retry-After.",
        "parameters": [
          {
            "name": "dominio",
            "in": "path",
            "required": true,
            "description": "Domínio do site, sem https:// (ex.: suaempresa.com.br).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Envelope da leitura.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvelopeDeLeitura"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Sem bearer válido (missing_token / invalid_token). O corpo traz `auth` e `sandbox`.",
            "headers": {
              "WWW-Authenticate": {
                "description": "Bearer resource_metadata=\"https://explorigen.io/.well-known/oauth-protected-resource\", scope=\"site.read prontidao.read\" — o apontador para a metadata do recurso protegido (RFC 9728).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token sem o escopo exigido (insufficient_scope).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Dois casos, distinguidos pelo corpo: cota da API excedida (`error: rate_limited`, forma `Error`) ou instrumento em pausa (`estado: limite`, com `tentarEm`). Em ambos, `Retry-After` em segundos.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/EnvelopeDeLeitura"
                    },
                    {
                      "$ref": "#/components/schemas/Error"
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Instrumento indisponível.",
            "headers": {
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/EnvelopeDeLeitura"
                    },
                    {
                      "$ref": "#/components/schemas/Error"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sandbox/paginas": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Sandbox"
        ],
        "security": [],
        "operationId": "sandboxListarPaginas",
        "summary": "Lista paginada das páginas públicas",
        "description": "Páginas do índice com rota, URL, título, descrição, seção e lastmod. Paginação por `limite` e `cursor`; `proximo` é o cursor da página seguinte, ausente na última. Sandbox (test mode): dados fixos, sem token, `X-Sandbox: true` e `sandbox: true` no corpo; um bearer, se vier, é validado e ecoado.",
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "description": "Itens por página, 1..100 (padrão 50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Índice inicial em base64url, devolvido em `proximo` da página anterior.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página da lista.",
            "headers": {
              "X-Sandbox": {
                "description": "Sempre `true` nas rotas do sandbox.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaDePaginas"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sandbox/paginas/{rota}": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Sandbox"
        ],
        "security": [],
        "operationId": "sandboxLerPagina",
        "summary": "Uma página em markdown",
        "description": "O markdown (espelho .md) de uma página do índice. Sandbox (test mode): dados fixos, sem token, `X-Sandbox: true` e `sandbox: true` no corpo; um bearer, se vier, é validado e ecoado.",
        "parameters": [
          {
            "name": "rota",
            "in": "path",
            "required": true,
            "description": "Rota da página sem a barra inicial (ex.: `solucoes/seo-tecnico`). Só rotas presentes em /agentes/indice.json; fora dele, 404.",
            "schema": {
              "type": "string"
            },
            "allowReserved": true
          }
        ],
        "responses": {
          "200": {
            "description": "A página.",
            "headers": {
              "X-Sandbox": {
                "description": "Sempre `true` nas rotas do sandbox.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginaCompleta"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sandbox/busca": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Sandbox"
        ],
        "security": [],
        "operationId": "sandboxBuscar",
        "summary": "Busca lexical nas páginas",
        "description": "Busca por termos (keyword search) no título, descrição e texto das páginas; sem ranking semântico. Sandbox (test mode): dados fixos, sem token, `X-Sandbox: true` e `sandbox: true` no corpo; um bearer, se vier, é validado e ecoado.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Termos de busca (obrigatório; vazio → 400).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limite",
            "in": "query",
            "description": "Resultados, 1..20 (padrão 8).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 8
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resultados.",
            "headers": {
              "X-Sandbox": {
                "description": "Sempre `true` nas rotas do sandbox.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultadoDeBusca"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sandbox/solucoes": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Sandbox"
        ],
        "security": [],
        "operationId": "sandboxListarSolucoes",
        "summary": "Soluções e objetivos",
        "description": "As soluções do catálogo e as cinco portas por objetivo de negócio. Sandbox (test mode): dados fixos, sem token, `X-Sandbox: true` e `sandbox: true` no corpo; um bearer, se vier, é validado e ecoado.",
        "responses": {
          "200": {
            "description": "Soluções e objetivos.",
            "headers": {
              "X-Sandbox": {
                "description": "Sempre `true` nas rotas do sandbox.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Solucoes"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sandbox/precos": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Sandbox"
        ],
        "security": [],
        "operationId": "sandboxListarPrecos",
        "summary": "Preços públicos",
        "description": "Os produtos com preço público (o mesmo de /pricing.md); os demais serviços são sob proposta (custom pricing). Sandbox (test mode): dados fixos, sem token, `X-Sandbox: true` e `sandbox: true` no corpo; um bearer, se vier, é validado e ecoado.",
        "responses": {
          "200": {
            "description": "Preços.",
            "headers": {
              "X-Sandbox": {
                "description": "Sempre `true` nas rotas do sandbox.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Precos"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sandbox/prontidao/{dominio}": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Sandbox"
        ],
        "security": [],
        "operationId": "sandboxLerProntidao",
        "summary": "Leitura de prontidão gravada de um domínio",
        "description": "Envelope de leitura com dados fixos, domínio reescrito para o pedido e `medidoEm` nulo. Nunca toca o instrumento nem o armazenamento. Sandbox (test mode): dados fixos, sem token, `X-Sandbox: true` e `sandbox: true` no corpo; um bearer, se vier, é validado e ecoado.",
        "parameters": [
          {
            "name": "dominio",
            "in": "path",
            "required": true,
            "description": "Domínio do site, sem https:// (ex.: suaempresa.com.br).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Envelope da leitura.",
            "headers": {
              "X-Sandbox": {
                "description": "Sempre `true` nas rotas do sandbox.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvelopeDeLeitura"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetro ou corpo fora da forma (invalid_request).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Rota ou página fora do índice (not_found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota excedida (rate_limited). Espere o `Retry-After` em segundos; a política está em /api/versioning.md.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requisições permitidas na janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Remaining": {
                "description": "Quantas ainda cabem nesta janela.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "RateLimit-Reset": {
                "description": "Segundos até a janela virar.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "A política, em item estruturado: `\"v1\";q=120;w=60` (com token) ou `\"v1-public\";q=60;w=60` (sem token).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "O estado, em item estruturado: `\"v1\";r=119;t=42` — os mesmos números dos três campos acima.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Segundos até tentar de novo.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/agent/identity": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "post": {
        "tags": [
          "Autenticação de agentes"
        ],
        "operationId": "registrarAgente",
        "summary": "Registro anônimo (agent_auth.identity_endpoint)",
        "description": "Registra uma sessão de agente sem conta: `{ \"type\": \"anonymous\" }` devolve `registration_id` e uma `identity_assertion` (JWT, 24 h) para trocar em /agent/token. `service_auth` e `identity_assertion` não são suportados (400). Corpo acima de 4 KB → 413. GET responde 405 com `Allow: POST, OPTIONS`.",
        "security": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única desta operação, escolhida pelo cliente (ASCII visível, até 255 caracteres). Repetir o pedido com a mesma chave e o mesmo corpo devolve a MESMA resposta, marcada com `Idempotency-Replayed: true`, em vez de emitir credencial nova. Mesma chave com corpo diferente é 422. A resposta guardada expira junto com o que ela carrega (24 h no registro, 1 h na troca).",
            "schema": {
              "type": "string",
              "maxLength": 255,
              "pattern": "^[\\x21-\\x7e]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PedidoDeRegistro"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registro criado.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "`true` quando a resposta é a repetição de uma emissão anterior, e não uma emissão nova.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "Idempotency-Status": {
                "description": "`unsupported` quando o ambiente não tem armazenamento para deduplicar: a chave foi aceita e ignorada, e a emissão é nova.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "unsupported"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistroAnonimo"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request, service_auth_not_enabled ou issuer_not_enabled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Método diferente de POST/OPTIONS.",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "POST, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo acima de 4 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Mesma Idempotency-Key com corpo diferente (idempotency_key_reuse).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Segredo de assinatura ausente no servidor (server_error).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/agent/token": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "post": {
        "tags": [
          "Autenticação de agentes"
        ],
        "operationId": "trocarAssertion",
        "summary": "Troca a identity_assertion por um access_token (token_endpoint)",
        "description": "Grant JWT-bearer (RFC 7523): `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>[&resource=<origem>/api/v1/]`, em formulário ou JSON. Devolve um access_token de 1 hora com `Cache-Control: no-store`. A mesma assertion troca de novo até expirar.",
        "security": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única desta operação, escolhida pelo cliente (ASCII visível, até 255 caracteres). Repetir o pedido com a mesma chave e o mesmo corpo devolve a MESMA resposta, marcada com `Idempotency-Replayed: true`, em vez de emitir credencial nova. Mesma chave com corpo diferente é 422. A resposta guardada expira junto com o que ela carrega (24 h no registro, 1 h na troca).",
            "schema": {
              "type": "string",
              "maxLength": 255,
              "pattern": "^[\\x21-\\x7e]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PedidoDeToken"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PedidoDeToken"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token emitido.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              },
              "Pragma": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-cache"
                  ]
                }
              },
              "Idempotency-Replayed": {
                "description": "`true` quando a resposta é a repetição de uma emissão anterior, e não uma emissão nova.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              },
              "Idempotency-Status": {
                "description": "`unsupported` quando o ambiente não tem armazenamento para deduplicar: a chave foi aceita e ignorada, e a emissão é nova.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "unsupported"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RespostaDeToken"
                }
              }
            }
          },
          "400": {
            "description": "invalid_grant, unsupported_grant_type, invalid_target ou invalid_request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Método diferente de POST/OPTIONS.",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "POST, OPTIONS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo acima do limite.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Mesma Idempotency-Key com corpo diferente (idempotency_key_reuse).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Segredo de assinatura ausente no servidor (server_error).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ask": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "NLWeb"
        ],
        "operationId": "perguntarPorGet",
        "summary": "Pergunta em linguagem natural (GET)",
        "description": "NLWeb 0.55: `?query=<texto>&streaming=false` devolve JSON; `streaming=true` (ou `Accept: text/event-stream`) devolve SSE com os eventos start, result, complete e done. Busca lexical (keyword search), sem modelo de linguagem.",
        "security": [],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "A pergunta.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "streaming",
            "in": "query",
            "description": "`true`/`1` para SSE.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false",
                "1",
                "0"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resultados (JSON) ou fluxo SSE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RespostaNLWeb"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Eventos start, result, complete, done; cada `data:` é JSON."
                }
              }
            }
          },
          "400": {
            "description": "Consulta vazia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FalhaNLWeb"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "NLWeb"
        ],
        "operationId": "perguntar",
        "summary": "Pergunta em linguagem natural (POST)",
        "description": "NLWeb 0.55: `{ \"query\": { \"text\": \"...\" } }` (também `{ \"query\": \"...\" }` ou `{ \"question\": \"...\" }`). `prefer.streaming: true` ou `Accept: text/event-stream` devolve SSE. Busca lexical (keyword search). Corpo acima de 64 KB → 413.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PedidoNLWeb"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultados (JSON) ou fluxo SSE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RespostaNLWeb"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Eventos start, result, complete, done; cada `data:` é JSON."
                }
              }
            }
          },
          "400": {
            "description": "Consulta ausente (`Missing query.text`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FalhaNLWeb"
                }
              }
            }
          },
          "413": {
            "description": "Corpo acima de 64 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/ia/leitura": {
      "servers": [
        {
          "url": "https://explorigen.io"
        }
      ],
      "get": {
        "tags": [
          "Leitura de prontidão"
        ],
        "operationId": "lerLeituraGravada",
        "summary": "Leitura de prontidão gravada (o que a página /diagnostico-de-visibilidade-cognitiva consulta)",
        "description": "Consulta a leitura gravada de um domínio sem gastar cota do instrumento. `estado` diz o que aconteceu: pronto, parcial, ausente, limite (com `tentarEm`), invalido, inalcancavel ou erro. Medir é ação da página /diagnostico-de-visibilidade-cognitiva (POST com `{ \"site\" }`, 3 medições por visitante a cada 24 h), não desta operação.",
        "security": [],
        "parameters": [
          {
            "name": "site",
            "in": "query",
            "required": true,
            "description": "Domínio, sem https://.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Envelope da leitura (estado pronto, parcial, ausente ou limite).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvelopeDeLeitura"
                }
              }
            }
          },
          "400": {
            "description": "Domínio inválido (`estado: invalido`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvelopeDeLeitura"
                }
              }
            }
          },
          "503": {
            "description": "Instrumento em pausa ou indisponível (`estado: erro` ou `limite`, com `tentarEm`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvelopeDeLeitura"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "agentAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Access token obtido em duas chamadas sem conta (POST /agent/identity → POST /agent/token); roteiro em https://explorigen.io/auth.md. Escopos: site.read (ler páginas, busca e catálogo (read pages, search, catalog)); prontidao.read (consultar leituras de prontidão gravadas (read recorded readiness scores))."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Forma única de todo erro JSON (§13.5 do contrato).",
        "required": [
          "error",
          "error_description"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Código curto e estável. Emitidos: invalid_request, service_auth_not_enabled, issuer_not_enabled, invalid_grant, unsupported_grant_type, invalid_target, missing_token, invalid_token, insufficient_scope, not_found, payload_too_large, server_error."
          },
          "error_description": {
            "type": "string"
          },
          "auth": {
            "type": "string",
            "format": "uri",
            "description": "Só no 401: a URL de auth.md."
          },
          "sandbox": {
            "type": "string",
            "format": "uri",
            "description": "Só no 401: a base do sandbox."
          }
        }
      },
      "Endpoint": {
        "type": "object",
        "required": [
          "metodo",
          "caminho",
          "escopo",
          "descricao"
        ],
        "properties": {
          "metodo": {
            "type": "string"
          },
          "caminho": {
            "type": "string"
          },
          "escopo": {
            "type": "string",
            "description": "Escopo exigido, ou vazio quando público."
          },
          "descricao": {
            "type": "string"
          }
        }
      },
      "Indice": {
        "type": "object",
        "required": [
          "nome",
          "versao",
          "documentacao",
          "openapi",
          "auth",
          "sandbox",
          "endpoints",
          "escopos",
          "politicaVersao"
        ],
        "properties": {
          "nome": {
            "type": "string"
          },
          "versao": {
            "type": "string"
          },
          "documentacao": {
            "type": "string",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "auth": {
            "type": "string",
            "format": "uri"
          },
          "sandbox": {
            "type": "string",
            "format": "uri"
          },
          "endpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Endpoint"
            }
          },
          "escopos": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "politicaVersao": {
            "type": "string"
          },
          "versionamento": {
            "type": "string",
            "format": "uri",
            "description": "A política completa de versão, depreciação e cota, em markdown."
          }
        }
      },
      "IndiceAutenticado": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Indice"
          },
          {
            "type": "object",
            "required": [
              "registrado_como",
              "sandbox_token"
            ],
            "properties": {
              "registrado_como": {
                "type": "string",
                "description": "O registration_id (sub) do token."
              },
              "sandbox_token": {
                "type": "boolean"
              }
            }
          }
        ]
      },
      "Pagina": {
        "type": "object",
        "required": [
          "rota",
          "url",
          "titulo",
          "descricao",
          "secao",
          "lastmod"
        ],
        "properties": {
          "rota": {
            "type": "string",
            "examples": [
              "/solucoes/seo-tecnico"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "titulo": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "secao": {
            "type": "string",
            "enum": [
              "home",
              "solucoes",
              "blog",
              "diagnostico",
              "institucional",
              "resultados",
              "metodo",
              "comecar",
              "seo-e-geo"
            ]
          },
          "lastmod": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ListaDePaginas": {
        "type": "object",
        "description": "Envelope de paginação (§13.4): `cursor` é o da página atual quando houve, `proximo` o da seguinte.",
        "required": [
          "itens",
          "total",
          "limite"
        ],
        "properties": {
          "itens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pagina"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limite": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "cursor": {
            "type": "string"
          },
          "proximo": {
            "type": "string",
            "description": "Ausente na última página."
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "PaginaCompleta": {
        "type": "object",
        "required": [
          "rota",
          "url",
          "titulo",
          "descricao",
          "markdown"
        ],
        "properties": {
          "rota": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "titulo": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "markdown": {
            "type": "string",
            "description": "O espelho .md, com frontmatter."
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "ItemDeBusca": {
        "type": "object",
        "required": [
          "rota",
          "url",
          "titulo",
          "descricao",
          "trecho",
          "pontuacao"
        ],
        "properties": {
          "rota": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "titulo": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "trecho": {
            "type": "string",
            "description": "Cerca de 200 caracteres ao redor do primeiro termo."
          },
          "pontuacao": {
            "type": "number"
          }
        }
      },
      "ResultadoDeBusca": {
        "type": "object",
        "required": [
          "consulta",
          "itens",
          "total",
          "limite"
        ],
        "properties": {
          "consulta": {
            "type": "string"
          },
          "itens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemDeBusca"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limite": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "Solucao": {
        "type": "object",
        "required": [
          "slug",
          "nome",
          "titulo",
          "resumo",
          "categoria",
          "url"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "nome": {
            "type": "string"
          },
          "titulo": {
            "type": "string"
          },
          "resumo": {
            "type": "string"
          },
          "categoria": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        }
      },
      "Objetivo": {
        "type": "object",
        "required": [
          "slug",
          "nome",
          "titulo",
          "url"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "nome": {
            "type": "string"
          },
          "titulo": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        }
      },
      "Solucoes": {
        "type": "object",
        "required": [
          "solucoes",
          "objetivos"
        ],
        "properties": {
          "solucoes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Solucao"
            }
          },
          "objetivos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Objetivo"
            }
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "Preco": {
        "type": "object",
        "required": [
          "valor",
          "moeda",
          "texto"
        ],
        "properties": {
          "valor": {
            "type": "string",
            "description": "Decimal como texto (ex.: \"997.00\"); \"0\" para grátis."
          },
          "moeda": {
            "type": "string",
            "enum": [
              "BRL"
            ]
          },
          "texto": {
            "type": "string",
            "description": "Como aparece no site."
          }
        }
      },
      "Produto": {
        "type": "object",
        "required": [
          "id",
          "nome",
          "descricao",
          "url",
          "preco"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "dpa",
              "leitura"
            ]
          },
          "nome": {
            "type": "string"
          },
          "sigla": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "preco": {
            "$ref": "#/components/schemas/Preco"
          },
          "prazo": {
            "type": "string"
          },
          "pagamento": {
            "type": "string",
            "format": "uri"
          },
          "inclui": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "limites": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Precos": {
        "type": "object",
        "required": [
          "produtos",
          "demais",
          "moeda",
          "fonte"
        ],
        "properties": {
          "produtos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Produto"
            }
          },
          "demais": {
            "type": "string",
            "enum": [
              "sob proposta (custom pricing)"
            ]
          },
          "moeda": {
            "type": "string",
            "enum": [
              "BRL"
            ]
          },
          "fonte": {
            "type": "string",
            "format": "uri",
            "description": "A URL de pricing.md."
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "EnvelopeDeLeitura": {
        "type": "object",
        "description": "O envelope da leitura de prontidão (modelo essentials do instrumento ora.ai, traduzido).",
        "required": [
          "estado",
          "dominio"
        ],
        "properties": {
          "estado": {
            "type": "string",
            "enum": [
              "pronto",
              "parcial",
              "ausente",
              "limite",
              "invalido",
              "inalcancavel",
              "erro"
            ]
          },
          "dominio": {
            "type": [
              "string",
              "null"
            ]
          },
          "hostFinal": {
            "type": "string",
            "description": "Quando o endereço redireciona, a nota é deste host."
          },
          "mensagem": {
            "type": "string"
          },
          "tentarEm": {
            "type": "integer",
            "description": "Segundos até poder tentar de novo. Só em `limite`."
          },
          "ausente": {
            "type": "boolean",
            "description": "Presente e `true` quando não há leitura (ferramenta MCP e API v1)."
          },
          "medir": {
            "type": "string",
            "format": "uri",
            "description": "Onde medir quando não há leitura (/diagnostico-de-visibilidade-cognitiva)."
          },
          "leitura": {
            "type": "object",
            "description": "Só em `pronto`/`parcial`.",
            "properties": {
              "dominio": {
                "type": "string"
              },
              "hostFinal": {
                "type": "string"
              },
              "situacao": {
                "type": "string",
                "enum": [
                  "completa",
                  "parcial",
                  "travada"
                ]
              },
              "medidoEm": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "nota": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "maximum": 100,
                "description": "Corte dos essenciais."
              },
              "rotulo": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "canonica": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "A régua completa do instrumento: nota 0-100 e grau A+ a F.",
                "properties": {
                  "nota": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "grau": {
                    "type": "string"
                  }
                }
              },
              "camadas": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "lacunas": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "resumo": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "additionalProperties": true
          },
          "fonte": {
            "type": "object",
            "properties": {
              "instrumento": {
                "type": "string",
                "enum": [
                  "ora.ai",
                  "fixture"
                ]
              },
              "contrato": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "doCache": {
                "type": "boolean"
              },
              "idadeSegundos": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "sandbox": {
            "type": "boolean"
          }
        }
      },
      "PedidoDeRegistro": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "anonymous"
            ],
            "description": "Só `anonymous`. `service_auth` → 400 service_auth_not_enabled; `identity_assertion` → 400 issuer_not_enabled."
          }
        }
      },
      "RegistroAnonimo": {
        "type": "object",
        "required": [
          "registration_id",
          "registration_type",
          "identity_assertion",
          "assertion_expires",
          "pre_claim_scopes",
          "post_claim_scopes",
          "scopes"
        ],
        "properties": {
          "registration_id": {
            "type": "string",
            "pattern": "^reg_[A-Za-z0-9_-]{20}$"
          },
          "registration_type": {
            "type": "string",
            "enum": [
              "anonymous"
            ]
          },
          "identity_assertion": {
            "type": "string",
            "description": "JWT compacto assinado pelo serviço, 24 h."
          },
          "assertion_expires": {
            "type": "string",
            "format": "date-time"
          },
          "pre_claim_scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "site.read",
                "prontidao.read"
              ]
            }
          },
          "post_claim_scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "site.read",
                "prontidao.read"
              ]
            }
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "site.read",
                "prontidao.read"
              ]
            }
          }
        }
      },
      "PedidoDeToken": {
        "type": "object",
        "required": [
          "grant_type",
          "assertion"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "urn:ietf:params:oauth:grant-type:jwt-bearer"
            ]
          },
          "assertion": {
            "type": "string",
            "description": "A identity_assertion do registro."
          },
          "resource": {
            "type": "string",
            "format": "uri",
            "description": "Opcional; se vier, tem de ser exatamente https://explorigen.io/api/v1/."
          }
        }
      },
      "RespostaDeToken": {
        "type": "object",
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "scope"
        ],
        "properties": {
          "access_token": {
            "type": "string"
          },
          "token_type": {
            "type": "string",
            "enum": [
              "Bearer"
            ]
          },
          "expires_in": {
            "type": "integer",
            "enum": [
              3600
            ]
          },
          "scope": {
            "type": "string",
            "examples": [
              "site.read prontidao.read"
            ]
          }
        }
      },
      "PedidoNLWeb": {
        "type": "object",
        "properties": {
          "query": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  }
                }
              }
            ]
          },
          "question": {
            "type": "string",
            "description": "Forma alternativa de `query`."
          },
          "prefer": {
            "type": "object",
            "properties": {
              "streaming": {
                "type": "boolean"
              }
            }
          },
          "streaming": {
            "type": "boolean"
          }
        }
      },
      "RespostaNLWeb": {
        "type": "object",
        "required": [
          "_meta",
          "query",
          "results",
          "summary"
        ],
        "properties": {
          "_meta": {
            "type": "object",
            "required": [
              "response_type",
              "version",
              "query_id"
            ],
            "properties": {
              "response_type": {
                "type": "string",
                "enum": [
                  "list"
                ]
              },
              "version": {
                "type": "string",
                "enum": [
                  "0.55"
                ]
              },
              "query_id": {
                "type": "string"
              }
            }
          },
          "query": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "@type",
                "url",
                "name",
                "description",
                "score",
                "site",
                "schema_object"
              ],
              "properties": {
                "@type": {
                  "type": "string",
                  "enum": [
                    "WebPage"
                  ]
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "score": {
                  "type": "number"
                },
                "site": {
                  "type": "string"
                },
                "schema_object": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "FalhaNLWeb": {
        "type": "object",
        "required": [
          "_meta",
          "error"
        ],
        "properties": {
          "_meta": {
            "type": "object",
            "properties": {
              "response_type": {
                "type": "string",
                "enum": [
                  "failure"
                ]
              },
              "version": {
                "type": "string",
                "enum": [
                  "0.55"
                ]
              }
            }
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}
