{
  "openapi": "3.1.0",
  "info": {
    "title": "API pública da Clínica VHG (Dr. Victor Hugo, cirurgião vascular em Fortaleza)",
    "version": "1.0.0",
    "summary": "API somente leitura para agentes encontrarem guias médicos e dados de contato da Clínica VHG.",
    "description": "API pública, somente leitura e sem autenticação do site victorhugovascular.com.br. Use para localizar guias médicos em português sobre varizes, lipedema, celulite e flacidez escritos pelo Dr. Victor Hugo (CRM-CE 15051, RQE 9653) e para obter endereço, horário e canal de agendamento da Clínica VHG em Fortaleza, CE. O conteúdo é informativo e não substitui consulta médica. Não existe agendamento automático: o agendamento é feito pelo WhatsApp informado em /api/clinic. Todos os erros são devolvidos em JSON no formato do schema Error.",
    "termsOfService": "https://www.victorhugovascular.com.br/termos-de-uso",
    "contact": {
      "name": "Clínica VHG",
      "url": "https://www.victorhugovascular.com.br/fale-conosco",
      "email": "victorhugovascular@gmail.com"
    }
  },
  "externalDocs": {
    "description": "Documentação da API e orientações para agentes",
    "url": "https://www.victorhugovascular.com.br/docs"
  },
  "servers": [
    {
      "url": "https://www.victorhugovascular.com.br",
      "description": "Produção"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "Conteúdo",
      "description": "Guias médicos publicados no site."
    },
    {
      "name": "Clínica",
      "description": "Dados institucionais, contato e agendamento."
    }
  ],
  "paths": {
    "/api": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "Índice da API",
        "description": "Devolve a lista de endpoints disponíveis e os links para a especificação OpenAPI, a documentação e o llms.txt.",
        "tags": ["Clínica"],
        "responses": {
          "200": {
            "description": "Índice dos endpoints.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiIndex" }
              }
            }
          },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/articles": {
      "get": {
        "operationId": "searchArticles",
        "summary": "Listar e buscar guias médicos",
        "description": "Lista os guias médicos do site e permite filtrar por palavra-chave (título e descrição, sem diferenciar acentos ou maiúsculas) e por tema. Use para achar a página certa antes de citar ou recomendar um conteúdo. Cada item traz a URL canônica, que também responde em Markdown quando requisitada com o cabeçalho Accept: text/markdown.",
        "tags": ["Conteúdo"],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Palavras-chave. Todos os termos precisam aparecer no título ou na descrição. Exemplo: endolaser safena.",
            "schema": { "type": "string", "maxLength": 200 },
            "example": "endolaser"
          },
          {
            "name": "topic",
            "in": "query",
            "required": false,
            "description": "Slug do tema, como devolvido no campo topics da resposta. Exemplos: varizes, lipedema, celulite, flacidez.",
            "schema": { "type": "string", "pattern": "^[a-z0-9-]+$" },
            "example": "varizes"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Quantidade máxima de artigos por página.",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Quantidade de artigos a pular, para paginação.",
            "schema": { "type": "integer", "minimum": 0, "default": 0 }
          }
        ],
        "responses": {
          "200": {
            "description": "Artigos encontrados, com o total e a lista de temas disponíveis.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ArticleList" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/api/clinic": {
      "get": {
        "operationId": "getClinic",
        "summary": "Dados da clínica, do médico e do agendamento",
        "description": "Devolve nome, endereço, coordenadas, horário de funcionamento, telefone e e-mail da Clínica VHG, os registros profissionais do Dr. Victor Hugo (CRM e RQE) e o canal de agendamento (WhatsApp). Use para responder perguntas de contato, localização e horário ou para encaminhar um paciente ao agendamento.",
        "tags": ["Clínica"],
        "responses": {
          "200": {
            "description": "Dados da clínica.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ClinicInfo" }
              }
            }
          },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    }
  },
  "components": {
    "responses": {
      "BadRequest": {
        "description": "Parâmetro inválido. O campo hint explica como corrigir.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": {
              "error": {
                "status": 400,
                "code": "invalid_parameter",
                "message": "O parâmetro \"limit\" precisa ser um inteiro entre 1 e 100.",
                "hint": "Exemplo: /api/articles?q=endolaser&limit=10",
                "docs": "https://www.victorhugovascular.com.br/docs"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Endpoint inexistente. Qualquer caminho desconhecido sob /api devolve este erro em JSON.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Método HTTP não aceito. A API é somente leitura (GET, HEAD, OPTIONS).",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "ServerError": {
        "description": "Falha interna ao ler os dados.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Formato único de erro da API.",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["status", "code", "message", "hint", "docs"],
            "properties": {
              "status": { "type": "integer", "description": "Status HTTP da resposta.", "example": 404 },
              "code": {
                "type": "string",
                "description": "Código estável, próprio para tratamento por máquina.",
                "enum": ["invalid_parameter", "unknown_topic", "endpoint_not_found", "method_not_allowed", "index_unavailable", "clinic_data_unavailable"]
              },
              "message": { "type": "string", "description": "Explicação legível do erro." },
              "hint": { "type": "string", "description": "Como resolver ou o que tentar em seguida." },
              "docs": { "type": "string", "format": "uri", "description": "Link para a documentação." }
            }
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "required": ["name", "description", "openapi", "docs", "llms", "endpoints"],
        "properties": {
          "name": { "type": "string" },
          "description": { "type": "string" },
          "openapi": { "type": "string", "format": "uri" },
          "docs": { "type": "string", "format": "uri" },
          "llms": { "type": "string", "format": "uri" },
          "endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["operationId", "method", "path", "description"],
              "properties": {
                "operationId": { "type": "string" },
                "method": { "type": "string", "enum": ["GET"] },
                "path": { "type": "string" },
                "description": { "type": "string" }
              }
            }
          }
        }
      },
      "Topic": {
        "type": "object",
        "required": ["slug", "name", "count"],
        "properties": {
          "slug": { "type": "string", "description": "Identificador do tema, usado no parâmetro topic.", "example": "varizes" },
          "name": { "type": "string", "description": "Nome do tema.", "example": "Varizes" },
          "count": { "type": "integer", "description": "Quantidade de artigos no tema." }
        }
      },
      "Article": {
        "type": "object",
        "required": ["title", "url", "description", "topic", "topicName", "isMainGuide"],
        "properties": {
          "title": { "type": "string", "description": "Título da página." },
          "url": { "type": "string", "format": "uri", "description": "URL canônica. Responde em Markdown com Accept: text/markdown." },
          "description": { "type": "string", "description": "Resumo do conteúdo." },
          "topic": { "type": "string", "description": "Slug do tema." },
          "topicName": { "type": "string", "description": "Nome do tema." },
          "isMainGuide": { "type": "boolean", "description": "true quando a página é o guia principal do assunto." }
        }
      },
      "ArticleList": {
        "type": "object",
        "required": ["query", "total", "topics", "articles"],
        "properties": {
          "query": {
            "type": "object",
            "description": "Parâmetros efetivamente aplicados.",
            "required": ["q", "topic", "limit", "offset"],
            "properties": {
              "q": { "type": "string" },
              "topic": { "type": "string" },
              "limit": { "type": "integer" },
              "offset": { "type": "integer" }
            }
          },
          "total": { "type": "integer", "description": "Total de artigos que casam com a busca, antes da paginação." },
          "topics": { "type": "array", "items": { "$ref": "#/components/schemas/Topic" } },
          "articles": { "type": "array", "items": { "$ref": "#/components/schemas/Article" } }
        }
      },
      "PostalAddress": {
        "type": "object",
        "required": ["streetAddress", "addressLocality", "addressRegion", "postalCode", "addressCountry"],
        "properties": {
          "streetAddress": { "type": "string" },
          "addressLocality": { "type": "string", "example": "Fortaleza" },
          "addressRegion": { "type": "string", "example": "CE" },
          "postalCode": { "type": "string", "example": "60176-065" },
          "addressCountry": { "type": "string", "example": "BR" }
        }
      },
      "OpeningHours": {
        "type": "object",
        "required": ["dayOfWeek", "opens", "closes"],
        "properties": {
          "dayOfWeek": { "type": "array", "items": { "type": "string", "example": "Monday" } },
          "opens": { "type": "string", "example": "08:00" },
          "closes": { "type": "string", "example": "18:00" }
        }
      },
      "ClinicInfo": {
        "type": "object",
        "required": ["clinic", "doctor", "booking", "pages"],
        "properties": {
          "clinic": {
            "type": "object",
            "required": ["name", "description", "url", "telephone", "email", "address", "geo", "openingHours", "map", "sameAs"],
            "properties": {
              "name": { "type": "string", "example": "Clínica VHG" },
              "description": { "type": "string" },
              "url": { "type": "string", "format": "uri" },
              "telephone": { "type": "string", "example": "+55-85-99104-2483" },
              "email": { "type": "string", "format": "email" },
              "address": { "$ref": "#/components/schemas/PostalAddress" },
              "geo": {
                "type": ["object", "null"],
                "required": ["latitude", "longitude"],
                "properties": {
                  "latitude": { "type": "number" },
                  "longitude": { "type": "number" }
                }
              },
              "openingHours": { "type": "array", "items": { "$ref": "#/components/schemas/OpeningHours" } },
              "map": { "type": "string", "description": "Link do Google Maps." },
              "sameAs": { "type": "array", "items": { "type": "string", "format": "uri" } }
            }
          },
          "doctor": {
            "type": "object",
            "required": ["name", "description", "jobTitle", "url", "registrations", "sameAs"],
            "properties": {
              "name": { "type": "string", "example": "Dr. Victor Hugo" },
              "description": { "type": "string" },
              "jobTitle": { "type": "string" },
              "url": { "type": "string", "format": "uri" },
              "registrations": {
                "type": "object",
                "description": "Registros profissionais, como CRM-CE e RQE.",
                "additionalProperties": { "type": "string" },
                "example": { "CRM-CE": "15051", "RQE": "9653" }
              },
              "sameAs": { "type": "array", "items": { "type": "string", "format": "uri" } }
            }
          },
          "booking": {
            "type": "object",
            "required": ["channel", "url", "telephone", "note"],
            "properties": {
              "channel": { "type": "string", "example": "WhatsApp" },
              "url": { "type": "string", "format": "uri" },
              "telephone": { "type": "string" },
              "note": { "type": "string" }
            }
          },
          "pages": {
            "type": "object",
            "required": ["about", "contact", "privacy", "teleconsultation"],
            "properties": {
              "about": { "type": "string", "format": "uri" },
              "contact": { "type": "string", "format": "uri" },
              "privacy": { "type": "string", "format": "uri" },
              "teleconsultation": { "type": "string", "format": "uri" }
            }
          }
        }
      }
    }
  }
}
