Integrate in 4 Steps
- Create a SERP API key
Register and log in → https://www.spindorai.com/api-keys → SERP API tab. Format:
sp_serp_… - POST https://www.spindorai.com/api/public-rank-finder/check
Content-Type: application/json,X-Spindora-Key: sp_serp_… - Handle JSON response
Use found, position, page and results[]. No polling — single request is enough.
- Show attribution
Near results: Powered by Spindora → https://www.spindorai.com
Overview
Spindora SERP API finds the ranking position of a domain for a keyword in Google (or DuckDuckGo / Yandex). Results return immediately — no async queue or polling. With an API key, monthly quota is tied to your user account — all SERP keys share the same pool.
API key required
For external calls
Sync response
POST /check → 200
Attribution
Required link
Authentication
A valid SERP API key is required for external integrations. Create keys from your dashboard; the full secret is shown only once.
| Method | Value |
|---|---|
| Header (recommended) | X-Spindora-Key: sp_serp_… |
| Bearer | Authorization: Bearer sp_serp_… |
Create keys at: https://www.spindorai.com/api-keys (login required)
Quotas & Plans
With API key (external integration)
- Quota is monthly per user — shared across all SERP keys.
- Plans: Free 50 · Starter 100 · Pro 200 · Pro+ 400 · Enterprise 800 requests/month.
- Remaining quota:
GET https://www.spindorai.com/api/api-hub/status(with Spindora session token; visible in dashboard). - Up to 10 active SERP keys.
Web UI (/sira-bulucu)
- Without API key, daily IP limit applies (default 30/day).
Buy plans: https://www.spindorai.com/api-key-satin-al
Request Flow
POST /check
Send url + keyword
Wait (≤60s)
SERP scan on server
200 OK
position + results[]
Unlike the SEO Analysis API, there is no task_id or poll loop.
Request Schema
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | Target site (domain or full URL) |
| keyword | string | Yes | Keyword to search |
| engine | "google" | "duckduckgo" | "yandex" | No | Default: google |
| location | string | No | Geo slug: tr, ankara, istanbul, us, uk, de… |
| locale | "tr" | "en" | No | Error message language |
| max_pages | integer 1–10 | No | Max SERP pages to scan (default 5) |
Endpoints
/checkCheck rank — main integration endpoint.
curl -X POST "https://www.spindorai.com/api/public-rank-finder/check" \
-H "Content-Type: application/json" \
-H "X-Spindora-Key: sp_serp_YOUR_KEY_HERE" \
-d '{
"url": "example.com",
"keyword": "seo aracı",
"engine": "google",
"location": "tr",
"locale": "tr",
"max_pages": 5
}'/quotaDaily IP quota for web UI. With API key, use /api-hub/status for monthly quota.
JSON Response Examples
Found (200)
{
"success": true,
"url": "example.com",
"keyword": "seo aracı",
"engine": "google",
"source": "google",
"location": "tr",
"found": true,
"position": 3,
"page": 1,
"results": [
{
"position": 1,
"page": 1,
"title": "En İyi SEO Araçları",
"url": "https://competitor.com/seo-araclari",
"description": "…",
"is_target": false
},
{
"position": 3,
"page": 1,
"title": "Example — SEO Aracı",
"url": "https://example.com/",
"description": "…",
"is_target": true
}
],
"message": "Siteniz 3. sırada (1. sayfa).",
"attribution": {
"text": "Powered by Spindora",
"url": "https://www.spindorai.com",
"required": true
}
}Not found (200)
{
"success": true,
"url": "example.com",
"keyword": "çok nadir kelime",
"engine": "google",
"location": "tr",
"found": false,
"position": null,
"page": null,
"results": [],
"message": "İlk 5 sayfada bulunamadı.",
"attribution": {
"text": "Powered by Spindora",
"url": "https://www.spindorai.com",
"required": true
}
}Attribution (Required)
In API mode the response includes an attribution object. It must be visible near results in your integration:
<a href="https://www.spindorai.com" target="_blank" rel="noopener noreferrer">
Powered by Spindora
</a>Code Examples
JavaScript (fetch)
const API = 'https://www.spindorai.com/api/public-rank-finder';
const KEY = 'sp_serp_YOUR_KEY_HERE';
async function checkRank(url, keyword) {
const res = await fetch(`${API}/check`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Spindora-Key': KEY,
},
body: JSON.stringify({
url,
keyword,
engine: 'google',
location: 'tr',
locale: 'tr',
max_pages: 5,
}),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.detail?.message || err.detail || res.statusText);
}
const data = await res.json();
// data.found, data.position, data.page, data.results
return data;
}Python (requests)
import requests
API = "https://www.spindorai.com/api/public-rank-finder"
KEY = "sp_serp_YOUR_KEY_HERE"
HEADERS = {"X-Spindora-Key": KEY, "Content-Type": "application/json"}
def check_rank(url: str, keyword: str) -> dict:
r = requests.post(
f"{API}/check",
headers=HEADERS,
json={
"url": url,
"keyword": keyword,
"engine": "google",
"location": "tr",
"locale": "tr",
"max_pages": 5,
},
timeout=60,
)
r.raise_for_status()
return r.json()
# result["found"], result["position"], result["results"]Node.js
const API = 'https://www.spindorai.com/api/public-rank-finder';
const KEY = 'sp_serp_YOUR_KEY_HERE';
async function checkRank(url, keyword) {
const res = await fetch(`${API}/check`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Spindora-Key': KEY,
},
body: JSON.stringify({
url,
keyword,
engine: 'google',
location: 'tr',
locale: 'tr',
max_pages: 5,
}),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.detail?.message || err.detail || res.statusText);
}
const data = await res.json();
// data.found, data.position, data.page, data.results
return data;
}PHP
<?php
$api = 'https://www.spindorai.com/api/public-rank-finder';
$key = 'sp_serp_YOUR_KEY_HERE';
function checkRank(string $url, string $keyword): array {
global $api, $key;
$ch = curl_init("$api/check");
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,
'keyword' => $keyword,
'engine' => 'google',
'location' => 'tr',
'locale' => 'tr',
'max_pages' => 5,
]),
CURLOPT_TIMEOUT => 60,
]);
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) {
throw new RuntimeException($body ?: "HTTP $code");
}
return json_decode($body, true);
}Response Fields
| Field | Description |
|---|---|
| found | Whether target domain was found in SERP |
| position | Global rank (1 = first) |
| page | SERP page number where found |
| results[] | SERP snippets (position, title, url, is_target) |
| engine | Requested search engine |
| source | Data source used (google, searxng, etc.) |
| message | Human-readable summary |
| attribution | Required display info |
Error Codes
| HTTP | Meaning | What to do |
|---|---|---|
| 401 | Invalid or missing API key | Verify sp_serp_ prefix |
| 403 | API plan expired | Renew plan at api-key-satin-al |
| 429 | Monthly quota exceeded | Upgrade plan or wait next month |
| 400 | Empty keyword or invalid body | Provide keyword field |
| 500 | Temporary SERP / server error | Retry after a short delay |
Integration Checklist
- ✓SERP API key created (sp_serp_…)
- ✓X-Spindora-Key sent on every POST /check
- ✓UI shows friendly message when found=false
- ✓429 shows upgrade path for monthly quota
- ✓Powered by Spindora link visible near results
- ✓Request timeout at least 60s (SERP scan may take time)
Brief for AI / LLMs
Paste this text or the OpenAPI JSON link when asking an AI to write integration code:
# Spindora SERP API — Integration Brief
Base URL: https://www.spindorai.com/api/public-rank-finder
Documentation: https://www.spindorai.com/developers/serp-api
OpenAPI JSON: https://www.spindorai.com/developers/serp-api.openapi.json
API Key: Register → log in → https://www.spindorai.com/api-keys → create key under SERP API tab (sp_serp_*)
## Authentication
Header: X-Spindora-Key: sp_serp_YOUR_KEY
Alternative: Authorization: Bearer sp_serp_YOUR_KEY
## Flow (synchronous — no polling)
POST /check
Body: {"url":"example.com","keyword":"seo tool","engine":"google","location":"tr","locale":"en","max_pages":5}
→ HTTP 200 returns position, page, results[]
## Quota
Monthly, user-level (shared across all SERP keys):
Free 50 | Starter 100 | Pro 200 | Pro+ 400 | Enterprise 800 / month
Remaining quota: GET https://www.spindorai.com/api/api-hub/status (Spindora session JWT)
## Requirements
- API key required for external integrations
- Show attribution in UI: Powered by Spindora → https://www.spindorai.com
## Error codes
401 invalid key | 403 plan expired | 429 monthly quota exceeded | 400 missing keyword | 500 temporary SERP errorOpenAPI: https://www.spindorai.com/developers/serp-api.openapi.json