REST API · v1 · Async

GEO Analysis API

Analyze how ChatGPT, Perplexity, Gemini and Claude read your site via API. One AI profile per request.

Base URLhttps://www.spindorai.com/api/public-geo-analysis
OpenAPI JSON

Share this page or OpenAPI with AI assistants to generate integration code.

Integrate in 5 Steps

  1. Create GEO API key

    https://www.spindorai.com/api-keysGEO Analiz API. Format: sp_geo_…

  2. POST https://www.spindorai.com/api/public-geo-analysis/analyzeX-Spindora-Key + JSON body
  3. Poll with task_id — GET /result/{task_id} her 2–3 sn
  4. Show profiles[] scores — geo_score, recommendations, vb.
  5. Attribution — Powered by Spindora linki zorunlu

Overview

GEO Analysis API crawls your page as AI bots would (GPTBot, PerplexityBot, GoogleOther, ClaudeBot). Select one profile per request. Returns GEO score, readability, schema quality, trust signals and recommendations. Requests are queued — get task_id first, then poll for results.

API key required

External calls

4 AI profiles

chatgpt · perplexity · gemini · claude

Attribution

Required link

AI Profiles

Send exactly one profile in the profiles array per request. Models use different User-Agents, score weights and evaluation lenses, so the same URL may yield different scores and recommendations.

ProfileSimulated botFocus
chatgptGPTBot (OpenAI)Chat quoting, FAQ-style answers
perplexityPerplexityBotSources, dates, factual depth
geminiGoogleOther (Google)Schema, entities, structured data
claudeClaudeBot (Anthropic)Long-form context, trust signals

Authentication

HeaderX-Spindora-Key: sp_geo_…
BearerAuthorization: Bearer sp_geo_…

Quotas & Plans

  • Monthly quota is user-level — shared across GEO keys.
  • Plans: Free 50 · Starter 100 · Pro 200 · Pro+ 400 · Enterprise 800 / month.
  • Remaining: GET https://www.spindorai.com/api/api-hub/status
  • Visual snapshots are not returned via API.

Request Flow

1

POST /analyze

Queue job

2

GET /result/{id}

Poll ~2.5s

3

200 OK

profiles[] ready

202 = pending · Analysis may take 30–120s

Request Schema

FieldTypeRequiredDescription
urlstring (URL)YesPage to analyze
profilesstring[] (length 1)NoExactly one: chatgpt | perplexity | gemini | claude. Default: ["chatgpt"]
language"tr" | "en"NoRecommendation language
locale"tr" | "en"NoError message language

Endpoints

POST/analyze

Queues GEO analysis.

cURL
curl -X POST "https://www.spindorai.com/api/public-geo-analysis/analyze" \
  -H "Content-Type: application/json" \
  -H "X-Spindora-Key: sp_geo_YOUR_KEY_HERE" \
  -d '{
    "url": "https://example.com",
    "profiles": ["chatgpt"],
    "language": "tr",
    "locale": "tr"
  }'
GET/result/{task_id}

Poll result — same API key.

cURL
curl "https://www.spindorai.com/api/public-geo-analysis/result/TASK_ID_HERE" \
  -H "X-Spindora-Key: sp_geo_YOUR_KEY_HERE"

JSON Response Examples

POST /analyze (200)

JSON
{
  "task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "message": "GEO analiziniz sıraya alındı. Lütfen bekleyin…",
  "mode": "api",
  "attribution": {
    "text": "Powered by Spindora",
    "url": "https://www.spindorai.com",
    "required": true,
    "html": "<a href=\"https://www.spindorai.com\" target=\"_blank\" rel=\"noopener\">Powered by Spindora</a>"
  }
}

GET /result (202)

JSON
{ "status": "pending" }

GET /result (200)

JSON
{
  "success": true,
  "url": "https://example.com",
  "average_geo_score": 72,
  "average_ai_readability_score": 68,
  "average_expertise_score": 61,
  "visual_snapshot_data_url": null,
  "visual_snapshots_data_urls": [],
  "profiles": [
    {
      "profile": "chatgpt",
      "status_code": 200,
      "crawlable": true,
      "crawlability_reason": "Erişilebilir",
      "geo_score": 74,
      "ai_readability_score": 70,
      "expertise_score": 63,
      "schema_score": 55,
      "word_count": 842,
      "found_schemas": ["WebPage", "Organization"],
      "missing_schemas": ["FAQPage"],
      "recommendations": [
        "FAQ schema ekleyin — AI yanıtlarında alıntılanma şansını artırır."
      ],
      "headline_verdict": "İçerik okunabilir; schema derinliği geliştirilebilir.",
      "top_strengths": ["Net H1 yapısı", "Yeterli kelime sayısı"],
      "top_gaps": ["FAQ yapısı eksik", "Güven sinyalleri zayıf"],
      "quick_wins": ["Meta description güncelleyin", "Yazar bilgisi ekleyin"]
    }
  ],
  "attribution": {
    "text": "Powered by Spindora",
    "url": "https://www.spindorai.com",
    "required": true
  }
}

Attribution (Required)

<a href="https://www.spindorai.com" target="_blank" rel="noopener noreferrer">
  Powered by Spindora
</a>

Code Examples

JavaScript

const API = 'https://www.spindorai.com/api/public-geo-analysis';
const KEY = 'sp_geo_YOUR_KEY_HERE';

async function analyzeGeo(url) {
  const start = await fetch(`${API}/analyze`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Spindora-Key': KEY,
    },
    body: JSON.stringify({
      url,
      profiles: ['chatgpt'],
      language: 'tr',
      locale: 'tr',
    }),
  });
  if (!start.ok) throw new Error(await start.text());
  const { task_id } = await start.json();

  for (let i = 0; i < 90; i++) {
    await new Promise((r) => setTimeout(r, 2500));
    const res = await fetch(`${API}/result/${task_id}`, {
      headers: { 'X-Spindora-Key': KEY },
    });
    if (res.status === 202) continue;
    if (!res.ok) throw new Error(await res.text());
    return res.json();
  }
  throw new Error('Timeout');
}

Python

import time
import requests

API = "https://www.spindorai.com/api/public-geo-analysis"
KEY = "sp_geo_YOUR_KEY_HERE"
HEADERS = {"X-Spindora-Key": KEY}

def analyze_geo(url: str) -> dict:
    r = requests.post(
        f"{API}/analyze",
        headers={**HEADERS, "Content-Type": "application/json"},
        json={
            "url": url,
            "profiles": ["chatgpt"],
            "language": "tr",
            "locale": "tr",
        },
        timeout=30,
    )
    r.raise_for_status()
    task_id = r.json()["task_id"]

    for _ in range(90):
        time.sleep(2.5)
        poll = requests.get(f"{API}/result/{task_id}", headers=HEADERS, timeout=30)
        if poll.status_code == 202:
            continue
        poll.raise_for_status()
        return poll.json()
    raise TimeoutError("GEO analysis timed out")

Response Fields

  • average_geo_score — Average GEO score (0–100)
  • profiles[] — Per-profile detail
  • visual_snapshots_data_urls — Always [] via API
  • attribution — Required display

Error Codes

HTTPMeaning
401Invalid API key
403Plan expired
429Monthly quota exceeded
202Still processing
500Analysis/queue error

Integration Checklist

  • sp_geo_ key created
  • Poll loop after POST /analyze
  • Wait on 202, parse on 200
  • No snapshots expected
  • Attribution visible
  • 429 upgrade message

Brief for AI / LLMs

AI prompt
# Spindora GEO Analysis API — Integration Brief

Base URL: https://www.spindorai.com/api/public-geo-analysis
Documentation: https://www.spindorai.com/developers/geo-analysis-api
OpenAPI JSON: https://www.spindorai.com/developers/geo-analysis-api.openapi.json
API Key: Register → log in → https://www.spindorai.com/api-keys → GEO Analysis API tab (sp_geo_*)

## Authentication
Header: X-Spindora-Key: sp_geo_YOUR_KEY

## Flow (async)
1. POST /analyze → {"url":"https://example.com","profiles":["chatgpt"],"language":"en","locale":"en"}
2. Get task_id
3. Poll GET /result/{task_id} every 2–3s
4. HTTP 202 = pending, HTTP 200 = ready

## Profiles (single selection)
chatgpt | perplexity | gemini | claude — each uses a distinct bot User-Agent and scoring lens

## Quota (monthly, user-level)
Free 50 | Starter 100 | Pro 200 | Pro+ 400 | Enterprise 800

## API notes
- No visual snapshots via API
- Required attribution: Powered by Spindora

## Errors
401 key | 403 plan | 429 quota | 202 pending | 500 failed

OpenAPI: https://www.spindorai.com/developers/geo-analysis-api.openapi.json