{
  "openapi": "3.1.0",
  "info": {
    "title": "DarkSearch.xyz API",
    "version": "1.0.0",
    "description": "Full-text search over web pages published on IPFS. Free, no key: 10 results per call, 10 requests per minute per IP (burst 5).",
    "termsOfService": "https://www.darksearch.xyz/terms.php"
  },
  "servers": [{ "url": "https://www.darksearch.xyz" }],
  "paths": {
    "/api.php": {
      "get": {
        "operationId": "search",
        "summary": "Search the index, or get its status with ?status",
        "description": "With `status` set, returns the index status instead of searching and ignores `q` and `limit`.",
        "parameters": [
          { "name": "q", "in": "query", "description": "Search words. Required unless `status` is set.", "schema": { "type": "string" }, "example": "wikipedia" },
          { "name": "limit", "in": "query", "description": "Results to return; capped at 10.", "schema": { "type": "integer", "minimum": 1, "maximum": 10, "default": 10 } },
          { "name": "status", "in": "query", "description": "Present (any value, or empty) to get the index status.", "allowEmptyValue": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Search results, or the index status with ?status",
            "content": { "application/json": { "schema": { "oneOf": [
              { "$ref": "#/components/schemas/SearchResults" },
              { "$ref": "#/components/schemas/Status" }
            ] } } }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "429": {
            "description": "Rate limited; retry after the given seconds",
            "headers": { "Retry-After": { "schema": { "type": "integer" } } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          },
          "502": { "$ref": "#/components/responses/Error" },
          "503": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SearchResults": {
        "type": "object",
        "required": ["total", "approximate", "results"],
        "properties": {
          "total": { "type": "integer", "description": "Total matches in the index" },
          "approximate": { "type": "boolean", "description": "Whether total is an estimate (searches for several common words)" },
          "results": { "type": "array", "items": { "$ref": "#/components/schemas/Result" } },
          "warning": { "type": "string", "description": "Set when the search was filtered; results is then empty" }
        }
      },
      "Result": {
        "type": "object",
        "required": ["cid", "title", "excerpt", "url"],
        "properties": {
          "cid": { "type": "string", "description": "IPFS content identifier" },
          "title": { "type": "string" },
          "excerpt": { "type": "string" },
          "url": { "type": "string", "format": "uri", "description": "The content on a public IPFS gateway" }
        }
      },
      "Status": {
        "type": "object",
        "required": ["pages", "keywords", "queue", "version"],
        "properties": {
          "pages": { "type": "integer" },
          "keywords": { "type": "integer" },
          "queue": { "type": "integer" },
          "version": { "type": "string" }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": { "error": { "type": "string" } }
      }
    },
    "responses": {
      "Error": {
        "description": "400 missing q; 502 unreadable indexer response; 503 indexer offline",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  }
}
