REST API · v1

SEO Analiz Aracı API

Ücretsiz on-page SEO analizini sitenize veya uygulamanıza entegre edin.

Temel URLhttps://www.spindorai.com/api/public-seo-analizi
OpenAPI JSON

Bu sayfa ve OpenAPI dosyası AI asistanlarına (ChatGPT, Claude, Cursor vb.) verilebilir — entegrasyon adımlarını otomatik üretirler.

5 Adımda Entegrasyon

  1. API anahtarı oluştur

    Kayıt olup giriş yapın, sidebar'daki Seo Analiz Aracı API Key Oluşturma menüsüne tıklayın: https://www.spindorai.com/seo-analizi-api-key (ücretsiz hesap). Anahtar formatı: sp_seo_… — tam değer yalnızca bir kez gösterilir.

  2. POST https://www.spindorai.com/api/public-seo-analizi/analyze

    Header: Content-Type: application/json, X-Spindora-Key: sp_seo_…

    Gövde: {"url":"https://example.com","keywords":[],"device":"desktop","locale":"tr"}

  3. task_id kaydet

    Yanıt örneği aşağıda (JSON Yanıt Örnekleri).

  4. GET https://www.spindorai.com/api/public-seo-analizi/result/{task_id}

    Aynı API key ile 2 saniyede bir poll et. 202 = bekliyor, 200 = sonuç hazır. Önerilen max bekleme: ~2 dakika (60 deneme).

  5. Attribution göster

    Sonuçların yanında zorunlu: Powered by Spindora → https://www.spindorai.com

Genel Bakış

Spindora SEO Analiz API, herhangi bir URL için on-page SEO denetimi yapar: başlık, meta, H1 yapısı, kelime sayısı, schema, outbound linkler, sunucu zamanlaması ve daha fazlası. İstekler asenkron işlenir — önce analiz kuyruğa alınır, ardından task_id ile sonuç poll edilir.

API key zorunlu

Harici isteklerde

30 analiz / gün

Anahtar başına

Attribution

Zorunlu link

Kimlik Doğrulama

Harici entegrasyonlar için geçerli bir API anahtarı zorunludur. Anahtarı panelden oluşturun; tam değer yalnızca oluşturma anında gösterilir.

YöntemDeğer
Header (önerilen)X-Spindora-Key: sp_seo_…
BearerAuthorization: Bearer sp_seo_…

Anahtar oluşturma: www.spindorai.com/seo-analizi-api-key (giriş gerekli)

Kota & Limitler

  • API anahtarı başına günde 30 analiz.
  • Kullanıcı başına en fazla 3 aktif anahtar.
  • API yanıtlarında screenshot döndürülmez — yalnızca www.spindorai.com web arayüzünde mevcuttur.

İstek Akışı

1

POST /analyze

Analizi kuyruğa al, task_id al

2

GET /result/{id}

~2 sn aralıkla poll et

3

200 OK

JSON sonuç hazır

202 = bekliyor · 200 = hazır

İstek Şeması

AlanTipZorunluAçıklama
urlstringEvetAnaliz edilecek tam URL (https://…)
keywordsstring[]HayırMax 3 anahtar kelime
device"desktop" | "mobile"HayırVarsayılan: desktop
locale"tr" | "en"HayırKontrol mesajlarının dili

Uç Noktalar

POST/analyze

Analizi başlatır.

Request body
{
  "url": "https://example.com",
  "keywords": ["seo", "kelime"],
  "device": "desktop",
  "locale": "tr"
}

Yanıt: { "task_id": "...", "mode": "api", "attribution": { ... } }

GET/result/{task_id}

Aynı API anahtarı ile poll edin. Hazır olduğunda tam JSON döner (screenshots boş).

GET/quota

Web arayüzü IP kotası (harici API için değil).

JSON Yanıt Örnekleri

Gerçek entegrasyonda bu yapıları bekleyin. screenshots her zaman boş dizidir.

POST /analyze → 200

JSON
{
  "task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "message": "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/{task_id} → 202 (bekliyor)

JSON
{ "status": "pending" }

GET /result/{task_id} → 200 (hazır, kısaltılmış)

JSON
{
  "success": true,
  "url": "https://example.com",
  "final_url": "https://example.com/",
  "device": "desktop",
  "keywords": ["seo"],
  "seo_score": 78,
  "word_count": 1240,
  "title_text": "Example Domain",
  "meta_description": "Example meta description",
  "h1_count": 1,
  "used_playwright": false,
  "screenshots": [],
  "checks": [
    { "id": "title", "title": "Sayfa başlığı", "status": "ok", "message": "Başlık mevcut." }
  ],
  "headings": [
    { "level": 1, "text": "Example Heading", "is_valid": true }
  ],
  "keyword_checks": [
    { "keyword": "seo", "in_title": true, "in_meta": false, "in_h1": true, "count": 3, "density_pct": 0.24 }
  ],
  "schema_types": ["WebPage"],
  "server": { "ttfb_sec": 0.18, "total_sec": 0.42 },
  "attribution": {
    "text": "Powered by Spindora",
    "url": "https://www.spindorai.com",
    "required": true
  }
}

Attribution (Zorunlu)

Entegre ettiğiniz arayüzde analiz sonuçlarının yakınında görünür ve tıklanabilir attribution göstermelisiniz:

HTML
<a href="https://www.spindorai.com" target="_blank" rel="noopener">Powered by Spindora</a>
Yanıttaki attribution nesnesi bu metni doğrular. Kaldırmak veya gizlemek kullanım şartlarını ihlal eder.

Kod Örnekleri

cURL — Start
curl -X POST "https://www.spindorai.com/api/public-seo-analizi/analyze" \
  -H "Content-Type: application/json" \
  -H "X-Spindora-Key: sp_seo_YOUR_KEY_HERE" \
  -d '{
    "url": "https://example.com",
    "keywords": ["seo", "analiz"],
    "device": "desktop",
    "locale": "tr"
  }'
cURL — Poll
curl "https://www.spindorai.com/api/public-seo-analizi/result/TASK_ID_HERE" \
  -H "X-Spindora-Key: sp_seo_YOUR_KEY_HERE"
JavaScript (browser)
const API = 'https://www.spindorai.com/api/public-seo-analizi';
const KEY = 'sp_seo_YOUR_KEY_HERE';

async function analyzeUrl(url) {
  const start = await fetch(`${API}/analyze`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Spindora-Key': KEY,
    },
    body: JSON.stringify({
      url,
      keywords: [],
      device: 'desktop',
      locale: 'tr',
    }),
  });
  const { task_id } = await start.json();

  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 2000));
    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');
}
Node.js
// Node.js 18+ (native fetch)
const API = 'https://www.spindorai.com/api/public-seo-analizi';
const KEY = 'sp_seo_YOUR_KEY_HERE';

async function analyzeUrl(url) {
  const startRes = await fetch(`${API}/analyze`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Spindora-Key': KEY,
    },
    body: JSON.stringify({
      url,
      keywords: [],
      device: 'desktop',
      locale: 'tr',
    }),
  });
  const { task_id } = await startRes.json();

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

API = "https://www.spindorai.com/api/public-seo-analizi"
KEY = "sp_seo_YOUR_KEY_HERE"
HEADERS = {"X-Spindora-Key": KEY}

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

    for _ in range(60):
        time.sleep(2)
        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("Analysis timed out")
PHP
<?php
$api = 'https://www.spindorai.com/api/public-seo-analizi';
$key = 'sp_seo_YOUR_KEY_HERE';

function analyze(string $url): array {
    global $api, $key;

    $ch = curl_init("$api/analyze");
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            "X-Spindora-Key: $key",
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'url' => $url,
            'keywords' => [],
            'device' => 'desktop',
            'locale' => 'tr',
        ]),
    ]);
    $body = curl_exec($ch);
    curl_close($ch);
    $taskId = json_decode($body, true)['task_id'];

    for ($i = 0; $i < 60; $i++) {
        sleep(2);
        $ch = curl_init("$api/result/$taskId");
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => ["X-Spindora-Key: $key"],
        ]);
        $poll = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($code === 202) continue;
        if ($code !== 200) throw new RuntimeException($poll);
        return json_decode($poll, true);
    }
    throw new RuntimeException('Timeout');
}
Java
import java.net.URI;
import java.net.http.*;
import java.time.Duration;

public class SpindoraSeoClient {
    private static final String API = "https://www.spindorai.com/api/public-seo-analizi";
    private static final String KEY = "sp_seo_YOUR_KEY_HERE";
    private static final HttpClient CLIENT = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(30))
        .build();

    public static String analyze(String url) throws Exception {
        String payload = "{\"url\":\"" + url + "\",\"keywords\":[],\"device\":\"desktop\",\"locale\":\"tr\"}";

        HttpRequest start = HttpRequest.newBuilder()
            .uri(URI.create(API + "/analyze"))
            .header("Content-Type", "application/json")
            .header("X-Spindora-Key", KEY)
            .POST(HttpRequest.BodyPublishers.ofString(payload))
            .build();

        String startJson = CLIENT.send(start, HttpResponse.BodyHandlers.ofString()).body();
        int marker = startJson.indexOf("\"task_id\":\"");
        String taskId = startJson.substring(marker + 11, startJson.indexOf('\"', marker + 11));

        for (int i = 0; i < 60; i++) {
            Thread.sleep(2000);
            HttpRequest poll = HttpRequest.newBuilder()
                .uri(URI.create(API + "/result/" + taskId))
                .header("X-Spindora-Key", KEY)
                .GET()
                .build();
            HttpResponse<String> res = CLIENT.send(poll, HttpResponse.BodyHandlers.ofString());
            if (res.statusCode() == 202) continue;
            if (res.statusCode() != 200) throw new RuntimeException(res.body());
            return res.body();
        }
        throw new RuntimeException("Timeout");
    }
}

Yanıt Alanları

AlanAçıklama
seo_score0–100 SEO skoru
checks[]Kontrol listesi (id, title, status, message)
headings[]H1–H6 yapısı
keyword_checks[]Anahtar kelime eşleşmeleri
word_countKelime sayısı
title_text, meta_descriptionSayfa başlığı ve meta
schema_types[]Bulunan schema türleri
serverTTFB, toplam süre
attributionZorunlu gösterim bilgisi

Hata Kodları

HTTPAnlamNe yapmalı
401Geçersiz veya eksik API anahtarıX-Spindora-Key header kontrol et
429Günlük kota dolduYarın tekrar dene veya yeni key
202Analiz devam ediyor2 sn sonra tekrar poll et
422URL erişilemedi / analiz hatasıURL ve erişilebilirlik kontrol et
500Sunucu / kuyruk hatasıKısa süre sonra tekrar dene

Hata gövdesi genelde { "detail": "..." }

Entegrasyon Kontrol Listesi

  • API anahtarı oluşturuldu ve güvenli saklanıyor
  • Her istekte X-Spindora-Key header gönderiliyor
  • POST /analyze sonrası task_id alınıp poll döngüsü kuruldu
  • 202 yanıtında bekleniyor, 200 gelince JSON parse ediliyor
  • screenshots[] API'de boş — UI'da göstermeye çalışma
  • Sonuç ekranında Powered by Spindora linki görünür
  • 429 için kullanıcıya anlamlı mesaj gösteriliyor

AI / LLM için özet

Bir AI asistanına entegrasyon yazdırırken bu metni veya OpenAPI JSON linkini yapıştırın:

Kopyala — AI prompt
# Spindora SEO Analiz API — Entegrasyon Özeti

Base URL: https://www.spindorai.com/api/public-seo-analizi
Dokümantasyon: https://www.spindorai.com/developers/seo-analizi-api
OpenAPI JSON: https://www.spindorai.com/developers/seo-analizi-api.openapi.json
API Key oluştur: Kayıt ol → giriş yap → sidebar'dan "Seo Analiz Aracı API Key Oluşturma" → https://www.spindorai.com/seo-analizi-api-key (ücretsiz hesap)

## Kimlik doğrulama
Header: X-Spindora-Key: sp_seo_YOUR_KEY
Alternatif: Authorization: Bearer sp_seo_YOUR_KEY

## Akış (asenkron)
1. POST /analyze → body: {"url":"https://example.com","keywords":[],"device":"desktop","locale":"tr"}
2. Yanıttan task_id al
3. GET /result/{task_id} — 2 saniyede bir poll et
4. HTTP 202 = devam ediyor, HTTP 200 = sonuç hazır

## Zorunluluklar
- API key harici entegrasyonlarda zorunlu
- Günlük limit: 30 analiz / API key
- screenshots[] API'de her zaman boş
- UI'da zorunlu attribution: <a href="https://www.spindorai.com">Powered by Spindora</a>

## Hata kodları
401 geçersiz key | 429 kota doldu | 202 bekliyor | 422 analiz hatası | 500 sunucu hatası

OpenAPI: https://www.spindorai.com/developers/seo-analizi-api.openapi.json