{
  "openapi": "3.1.0",
  "info": {
    "title": "Rabbytte API",
    "version": "1.0.0",
    "description": "Free, no-auth JSON access to a small human-curated web index. Every site was approved by a person. Please be gentle: public endpoints are rate-limited per IP."
  },
  "servers": [{ "url": "https://rabbytte.com" }],
  "paths": {
    "/api/search": {
      "get": {
        "summary": "Full-text search over the curated index",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1, "default": 1 } },
          { "name": "per", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 } }
        ],
        "responses": { "200": { "description": "Ranked results with title, url, description, tags, links, address, coordinates, and image path." } }
      }
    },
    "/api/ask": {
      "get": {
        "summary": "A question answered strictly from the index, with sources",
        "parameters": [{ "name": "q", "in": "query", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "{ answer, sources[] } grounded only in index entries." },
          "429": { "description": "Rate limit (6/min per IP)." },
          "501": { "description": "AI is not configured on this server." }
        }
      }
    },
    "/api/images": {
      "get": {
        "summary": "Matching sites' stored preview images",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer" } },
          { "name": "per", "in": "query", "schema": { "type": "integer", "maximum": 60 } }
        ],
        "responses": { "200": { "description": "Results with self-hosted image paths under /thumbs." } }
      }
    }
  }
}
