{
  "openapi": "3.0.3",
  "info": {
    "title": "Spindora SERP API (Rank Finder)",
    "version": "1.0.0",
    "description": "Google / DuckDuckGo / Yandex rank lookup API. Synchronous POST /check returns position and SERP snippets. Requires X-Spindora-Key header (format: sp_serp_*). Monthly quota is shared per user account across all keys. Mandatory attribution: Powered by Spindora linking to https://www.spindorai.com.",
    "contact": {
      "url": "https://www.spindorai.com/developers/serp-api"
    }
  },
  "servers": [
    {
      "url": "https://www.spindorai.com/api/public-rank-finder"
    }
  ],
  "security": [
    {
      "SpindoraApiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "SpindoraApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Spindora-Key",
        "description": "API key from https://www.spindorai.com/api-keys (prefix sp_serp_). Alternative: Authorization: Bearer sp_serp_..."
      }
    },
    "schemas": {
      "RankCheckRequest": {
        "type": "object",
        "required": ["url", "keyword"],
        "properties": {
          "url": {
            "type": "string",
            "minLength": 3,
            "maxLength": 500,
            "example": "example.com",
            "description": "Target site domain or URL"
          },
          "keyword": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "example": "seo aracı"
          },
          "engine": {
            "type": "string",
            "enum": ["google", "duckduckgo", "yandex"],
            "default": "google"
          },
          "location": {
            "type": "string",
            "maxLength": 40,
            "default": "tr",
            "description": "Geo slug e.g. tr, ankara, istanbul, us, uk, de"
          },
          "locale": {
            "type": "string",
            "enum": ["tr", "en"],
            "default": "tr",
            "description": "Error and message language"
          },
          "max_pages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 5,
            "description": "Max SERP pages to scan for the target domain"
          }
        }
      },
      "SerpResultItem": {
        "type": "object",
        "properties": {
          "position": { "type": "integer" },
          "page": { "type": "integer" },
          "title": { "type": "string" },
          "url": { "type": "string" },
          "description": { "type": "string" },
          "is_target": { "type": "boolean" }
        }
      },
      "RankCheckResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean" },
          "url": { "type": "string" },
          "keyword": { "type": "string" },
          "engine": { "type": "string" },
          "source": { "type": "string", "description": "Data source used (google, searxng, duckduckgo, etc.)" },
          "location": { "type": "string" },
          "found": { "type": "boolean" },
          "position": { "type": "integer", "nullable": true },
          "page": { "type": "integer", "nullable": true },
          "results": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SerpResultItem" }
          },
          "message": { "type": "string" },
          "attribution": {
            "type": "object",
            "properties": {
              "text": { "type": "string", "example": "Powered by Spindora" },
              "url": { "type": "string", "example": "https://www.spindorai.com" },
              "required": { "type": "boolean", "example": true }
            }
          }
        }
      },
      "QuotaExceeded": {
        "type": "object",
        "properties": {
          "message": { "type": "string" },
          "used": { "type": "integer" },
          "monthly_limit": { "type": "integer" }
        }
      }
    }
  },
  "paths": {
    "/check": {
      "post": {
        "summary": "Check Google rank for URL + keyword",
        "operationId": "checkRank",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/RankCheckRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rank result",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RankCheckResponse" }
              }
            }
          },
          "401": { "description": "Invalid or missing API key" },
          "403": { "description": "API plan expired" },
          "429": {
            "description": "Monthly quota exceeded",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QuotaExceeded" }
              }
            }
          },
          "500": { "description": "Temporary server / SERP fetch error" }
        }
      }
    },
    "/quota": {
      "get": {
        "summary": "Daily IP quota (web UI only)",
        "description": "When X-Spindora-Key is sent, returns a pointer to GET /api/api-hub/status for monthly API quota.",
        "responses": {
          "200": { "description": "Quota info" }
        }
      }
    }
  },
  "x-spindora-notes": [
    "Create API keys at https://www.spindorai.com/api-keys after login. Prefix sp_serp_*.",
    "Monthly plans: Free 50, Starter 100, Pro 200, Pro+ 400, Enterprise 800 requests/month (user-level, shared across keys).",
    "Check remaining quota: GET /api/api-hub/status with session auth (Bearer JWT from Spindora login).",
    "Show attribution near rank results in your UI when using API mode."
  ]
}
