Fejlesztői
API & Integráció
A GEOscore Next.js App Router alatt fut, az API route-ok REST-es POST végpontok. Az alábbiak a src/app/api/ alatt élnek.
POST /api/scan
Anonim scan végpont. Egyetlen domain auditja, eredmény mentve a scan_results táblába.
Request body:
{
"domain": "kovacsbolt.hu",
"private": false // V15: opcionális, default false. Ha true → kihagyva sitemap-ből
}Response (200):
{
"id": "uuid", // scan_results.id, későbbi /results/{id}-hez
"url": "https://kovacsbolt.hu",
"scores": { "overall": 72, "grade": "B", "categories": {...} },
"checks": [...], // ~30 GeoCheck objektum
"schemas": ["Organization", "FAQPage"],
"crawlerAccess": { "allowed": [...], "blocked": [...] },
"aiTests": [...], // 4 AITestResult
"lighthouse": { "performanceScore": 87, "lcp": 2.1, ... },
"actionPlan": [...], // priorizált javítási roadmap
"remaining": 4, // hátralévő scan-ek tier szerint
"cached": false // ha 24h-n belül futott már: true
}POST /api/scan-with-competitors (V9 — új)
N+1 párhuzamos scan, percentile- és gap-alapú összehasonlítás. Auth-only — a rate-limit költség miatt csak bejelentkezett user érheti el. Max 3 versenytárs (Vercel timeout védelem).
Request body:
{
"domain": "fő-domain.hu",
"competitors": ["versenytars1.hu", "versenytars2.hu", "versenytars3.hu"]
}Response:
{
"id": "uuid",
"main": { "domain": "...", "result": {...}, "score": 72, "grade": "B" },
"competitors": [
{ "domain": "...", "score": 68, "grade": "C", "isMain": false },
...
],
"benchmark": {
"ranking": [{ "position": 1, "domain": "...", "score": 75, "isMain": false }, ...],
"mainRank": 2,
"totalRanked": 4,
"percentile": 67, // százalékos pozíció a versenytársak között
"gapVsAverage": 4, // pontkülönbség a versenytársak átlagához képest
"averageCompetitor": 68,
"verdict": "A fő domain 4 ponttal a versenytársak átlaga felett."
}
}A V9 endpoint a kompetitor scan-eket automatikusan is_public: false-ra menti — más cégek domain-jeit nem indexeljük publikusan.
POST /api/audit (auth-only)
Bejelentkezett user audit végpontja, magasabb rate-limittel. Kéri az auth header-t (Authorization: Bearer <jwt>), a tier-szerinti rate-limit alkalmazódik.
Webhook (V14 — retry + idempotency)
Ha az admin felületen beállítasz egy WEBHOOK_URL-t, minden scan végén fire-and-forget POST megy oda. A V14 frissítés óta retry-zik (3x exponential backoff: 1s, 2s, 4s) és idempotency-key-t is küld.
Headers:
Content-Type: application/json
X-Idempotency-Key: <scan_uuid> // V14: dedup-key a retry-ok ellenBody (generic):
{
"domain": "kovacsbolt.hu",
"score": 72,
"grade": "B",
"topIssues": ["Hiányzó FAQ schema", "Nincs sitemap"],
"resultsLink": "https://geoscore.hu/results/uuid",
"categories": { "Technical": 80, "Content": 70, ... },
"summary": { "pass": 12, "warning": 5, "error": 3 }
}A webhook automatikusan formázott Slack-block / Discord-embed payload-ot küld, ha az URL hooks.slack.com vagy discord.com/api/webhooks. Egyébként a fenti generikus JSON.
Retry logika: 5xx, 408 timeout, 429 rate-limit, vagy network hibára 3-szor próbálkozunk (1s, 2s, 4s delay). 4xx (kivéve 408/429) → permanent error, nem retry-zünk. Az idempotency-key biztosítja, hogy a fogadó oldal felismerje a duplikátumot és ne dolgozza fel kétszer.
Rate-limit tier-ek
| Tier | Scan / nap | Megjegyzés |
|---|---|---|
| Anonymous | 5 | IP-alapú, VPN-nel kerülhető |
| Free (auth) | 5 | Auth user_id alapján |
| Basic | 10 | — |
| Pro | 30 | — |
| Agency | 100 | Multi-domain dashboardhoz ideális |
A rate-limit napi (UTC midnight reset). 24h cache: ugyanaz a domain+IP páros 24h-n belül cache-elt választ kap, nem fogyaszt új scan-keretet. A V9 kompetitor-benchmark N+1 scan-t számít fel egyszerre, tehát 4 domain × 1 lekérés = 4 scan a tier-edből.
V15 — Privát eredmény-flag (GDPR)
GDPR-érzékeny ügyfeleknél (pl. egy ügynökség sales-funnel-céllal scan-elt egy potenciális ügyfelet) az eredmény ne kerüljön a publikus sitemap-be. A scan body-ban add át:
POST /api/scan
{
"domain": "ugyfel-jelolt.hu",
"private": true
}A scan_results.is_public oszlop false-ra állítódik. A /sitemap.xml query WHERE is_public = true szűrővel fut, így a privát eredmény URL-jét nem indexeljük. Az eredmény-oldal (/results/{id}) továbbra is elérhető direct linkkel — csak nincs benne a sitemap-ben.
További endpoint-ok (csak referenciaként)
GET /api/results/[id]— egy konkrét scan-eredmény lekérésePOST /api/leads— lead form submit (név + email + domain)POST /api/dashboard/rescan— dashboard rescan (auth)POST /api/dashboard/domains— új domain hozzáadása (auth)PATCH /api/dashboard/settings— user beállítások (email_notifications)POST /api/cron/email-drip— éjszakai drip email cronGET /api/unsubscribe— RFC 8058 List-Unsubscribe