{
  "openapi": "3.1.0",
  "info": {
    "title": "Duvlify Docs Search API",
    "version": "1.0.0",
    "description": "Read-only access to the Duvlify documentation: search it, list its pages, and fetch a page as Markdown. This API does not touch product data and needs no authentication. The same tools are available over the Model Context Protocol at /mcp."
  },
  "servers": [
    {
      "url": "https://duvlify.dev"
    }
  ],
  "paths": {
    "/api/docs/search": {
      "get": {
        "operationId": "search",
        "summary": "Search the Duvlify documentation and return the most relevant passages, grouped by the page they come from",
        "description": "Search the Duvlify documentation and return the most relevant passages, grouped by the page they come from. Use this before answering any question about Duvlify — it searches the current published documentation directly, which is more reliable than recalling it. Pages are ordered by relevance; passages within a page are in reading order. Each passage reports its line range within the page, so you can tell whether you are seeing a small part of a long page and should call `fetch` for the rest. An empty result means nothing matched closely, not that the topic is missing — the response says what to do next, usually `list_pages` followed by `fetch`.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "What you want to know, in natural language or as keywords.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many passages to retrieve. Leave unset for 8, which suits most questions.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 25,
              "default": 8
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {}
            }
          },
          "400": {
            "description": "The request was rejected by the tool."
          },
          "429": {
            "description": "Rate limited. Honour `Retry-After`."
          }
        }
      }
    },
    "/api/docs/fetch": {
      "get": {
        "operationId": "fetch",
        "summary": "Return the complete Markdown of one Duvlify documentation page",
        "description": "Return the complete Markdown of one Duvlify documentation page. Takes the `url` reported by `search` or `list_pages`. Use it once `search` shows a page is relevant but you need the whole procedure, the full parameter table, or the surrounding context rather than a few passages.",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "The page URL, exactly as returned by `search` or `list_pages`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {}
            }
          },
          "400": {
            "description": "The request was rejected by the tool."
          },
          "429": {
            "description": "Rate limited. Honour `Retry-After`."
          }
        }
      }
    },
    "/api/docs/list_pages": {
      "get": {
        "operationId": "list_pages",
        "summary": "List the pages of the Duvlify documentation, with optional filters",
        "description": "List the pages of the Duvlify documentation, with optional filters. Use it to see what the documentation covers, to confirm a page exists before citing it, or to find what changed recently. It does not search page contents — use `search` for that.",
        "parameters": [
          {
            "name": "tab",
            "in": "query",
            "required": false,
            "description": "Restrict to one navigation area, for example `Guides`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Restrict to prose pages or API endpoint pages.",
            "schema": {
              "type": "string",
              "enum": [
                "page",
                "api-endpoint"
              ]
            }
          },
          {
            "name": "prefix",
            "in": "query",
            "required": false,
            "description": "Restrict to ids starting with this, for example `guides/`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "ISO date. Only pages changed on or after it.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {}
            }
          },
          "400": {
            "description": "The request was rejected by the tool."
          },
          "429": {
            "description": "Rate limited. Honour `Retry-After`."
          }
        }
      }
    },
    "/api/docs/report_issue": {
      "get": {
        "operationId": "report_issue",
        "summary": "Report a problem with a page of the Duvlify documentation — something inaccurate, out of date, missing or ambiguous",
        "description": "Report a problem with a page of the Duvlify documentation — something inaccurate, out of date, missing or ambiguous. Use it when you find a genuine defect while answering, not for questions. The report reaches the documentation team; nothing is published and you get no reply.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": true,
            "description": "Id or URL of the page the problem is on.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "problem",
            "in": "query",
            "required": true,
            "description": "What is wrong, missing or ambiguous, and what was expected instead.",
            "schema": {
              "type": "string",
              "maxLength": 2000
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "The kind of problem.",
            "schema": {
              "type": "string",
              "enum": [
                "inaccurate",
                "outdated",
                "missing",
                "unclear"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {}
            }
          },
          "400": {
            "description": "The request was rejected by the tool."
          },
          "429": {
            "description": "Rate limited. Honour `Retry-After`."
          }
        }
      }
    }
  }
}