GEO Audit API — Documentation
Audit Visibilité IA + SEO complet par URL. 141 checks locaux, 18 modules optionnels, 5 plateformes IA.
Vue d'ensemble
L'API expose plusieurs niveaux d'usage : audits consolidés (GEO + SEO + LLM live), audits par dimension (catégories SEO/GEO), modules unitaires (lancer un seul check : Core Web Vitals, backlinks, hallucination cross-LLM…), et endpoints spécialisés (Citation Tracker multi-LLM, Fan-out Coverage, prefill brand, exports HTML/PDF).
Architecture stateless one-shot : chaque appel est indépendant, pas de DB, cache mémoire opportuniste pour les API externes coûteuses (PSI, SERP, AIO).
URL de base
Tous les endpoints sont préfixés par /api. En développement local : http://localhost:3000.
Authentification
Aucune clé d'API requise pour l'usage public. Rate limit appliqué par IP : 5 audits/min et 30 audits/h (configurable via RATE_LIMIT_PER_IP_PER_MINUTE/HOUR). Les clés tierces (OpenRouter, Moz, Google PSI, DataForSEO, Google Places) sont configurées côté serveur dans .env.local — voir Variables d'env.
10.0.0.0/8, 192.168.0.0/16), loopback, link-local, ou métadata cloud (169.254.169.254) sont rejetées avec 400 SSRF_BLOCKED.
Démarrage rapide
1. Audit GEO basique (67 checks, ~10s)
2. Audit FULL (GEO + SEO + LLM live + DataForSEO, ~90s)
3. Lancer UN seul module (ex: Core Web Vitals seul)
Tiers d'endpoints
Les endpoints sont classés par fonction et coût opérationnel.
Audit consolidé
Les endpoints qui orchestrent plusieurs modules pour produire un rapport complet (GEO + SEO + LLM + intégrations).
Body
| Param | Type | Description |
|---|---|---|
url required | string | URL absolue à auditer |
options.timeout | number | Timeout crawl en ms (défaut 15000) |
options.skipLive | bool | Désactive Citation/Fanout/SXO/Hallucination même si OPENROUTER_API_KEY présente |
options.skipVisual | bool | Désactive Playwright/Browserless |
options.promptCount | 5-15 | Nombre de prompts Citation Tracker (défaut 8) |
options.enablePlacesLookup | bool | Active appel Google Places (payant) |
Réponse (résumé)
/api/audit/full mais retourne un flux Server-Sent Events. Émet des événements de progression : plan (liste des modules), module:start, module:done, module:skip, warning, et result final. Idéal pour UI temps réel.Format des événements
Audit GEO
Audits GEO par catégorie
Lance uniquement la catégorie ciblée — utile pour itérer sur une dimension précise.
Endpoints spécialisés GEO
llms.txt et llms-full.txt : présence, format, sections, conformité au standard llms.txt 0.9.Audit SEO
Audits SEO par catégorie
| Endpoint | Catégorie | Couvre |
|---|---|---|
POST /api/seo-audit/on-page | On-Page | title, meta, H1-H6, alt, anchors, canonicals |
POST /api/seo-audit/technical | Technical SEO | HTTPS, redirections, status codes, robots, headers |
POST /api/seo-audit/content | Content E-E-A-T | profondeur, expertise, autorité, fraîcheur |
POST /api/seo-audit/structured-data | Structured Data | JSON-LD, microdata, RDFa, sameAs |
POST /api/seo-audit/performance | Performance | poids HTML, ressources, LCP/CLS hints (sans CrUX) |
POST /api/seo-audit/crawlability | Crawlability | sitemap, robots, internal linking, depth |
POST /api/seo-audit/mobile | Mobile & UX | viewport, font-size, tap targets, responsive |
POST /api/seo-audit/authority | Authority | liens sortants, backlinks (si Moz/CC), trust signals |
POST /api/seo-audit/ai-readiness | AI Readiness | llms.txt, FAQ, citability blocks, schema |
Modules unitaires
Endpoint dynamique permettant de lancer UN seul module (Core Web Vitals, Backlinks, Hallucination, Citation Tracker, etc.) sans relancer tout l'audit FULL. Utilisé par la sidebar UI « Modules d'audit ».
ready/missing selon les variables d'environnement configurées côté serveur.Modules supportés
| moduleId | Tier | Description | Prérequis env |
|---|---|---|---|
crawl | core | HTML + robots + llms.txt + sitemap + probes IA | — |
geo | core | Audit GEO 67 checks | — |
seo | core | Audit SEO 74 checks | — |
cwv | premium | PSI v5 + CrUX 25 semaines (LCP, INP, CLS) | GOOGLE_API_KEY |
backlinks | premium | Common Crawl + Moz API | MOZ_API_KEY (optionnel) |
hreflang | core | Validation cross-page A↔B des return tags | — |
visual | core | Screenshots multi-viewport + cookie banner GDPR | — |
prefill | live | Extraction LLM brand/niche/concurrents | OPENROUTER_API_KEY |
sxo | live | Page-type + 4 personas (Relevance × Clarity × Trust × Action) | OPENROUTER_API_KEY |
local | premium | NAP + business profile + Google Places + 10 schemas | GOOGLE_PLACES_API_KEY |
dataforseo | premium | SERP top 10 + KW data + AI Overviews + Backlinks T3 | DATAFORSEO_AUTH |
geoEnrichments | core | PAA + Featured Snippet + Wikidata + Schema validator | — |
contentGap | premium | Crawl top 3 SERP + comparaison topics LLM | OPENROUTER_API_KEY + DATAFORSEO_AUTH |
tier2 | core | Outranking + JS rendering diff + Image deep + CRO | — |
multipage | core | Sitemap parser ou BFS depth=2 (50 pages) | — |
aiHallucination | premium | Cross-check 4 LLMs vs site officiel | OPENROUTER_API_KEY |
citation | live | Citation Tracker multi-LLM (freq, SoV, sentiment) | OPENROUTER_API_KEY |
fanout | live | Fan-out Coverage (décomposition de requête) | OPENROUTER_API_KEY |
Body
| Param | Type | Description |
|---|---|---|
url required | string | URL absolue |
options.brand | string | Évite un appel prefill pour les modules brand-aware |
options.niche | string | Évite un appel prefill |
options.competitors | array | Liste de domaines concurrents (citation, dataforseo) |
options.skipVisual | bool | Pour module visual |
options.promptCount | 5-15 | Pour module citation |
options.enablePlacesLookup | bool | Pour module local |
Réponse
{"ok":false, "skipped":"..."} en HTTP 200 (pas une erreur). En cas d'erreur réelle (timeout, API down) : {"ok":false, "error":"..."}.
LLM live
Endpoints dédiés aux modules LLM cross-modèles via OpenRouter (Gemini 2.5 Flash, GPT-4o mini, Claude Haiku 4.5, Perplexity Sonar).
Body
prompts, utilisez POST /api/citation/prefill pour les générer à partir de la niche.
brand, niche, suggestedCompetitors à partir d'une URL via LLM. Utilisé pour pré-remplir les autres endpoints LLM.Body
Réponse
Body
Exports
ExportPlanInput ou directement un CombinedAuditResponse.Réponse
Réponse
Variables d'environnement
Toutes les clés sont optionnelles — les modules concernés passent en mode dégradé (skip avec message d'info) si absentes.
| Variable | Module | Coût |
|---|---|---|
OPENROUTER_API_KEY | Citation, Fanout, SXO, Prefill, Hallucination, ContentGap | ~0.001-0.05$/run |
GOOGLE_API_KEY | PSI v5 + CrUX (Core Web Vitals) | Gratuit (quotas) |
MOZ_API_KEY | Backlinks Tier 1 (DA, PA, Spam Score, linking domains) | 2500 rows/mois free |
GOOGLE_PLACES_API_KEY | Local SEO — NAP cross-platform | ~0.025$/lookup |
DATAFORSEO_AUTH | SERP, KW, AIO, Backlinks T3, Content Gap | ~0.05-0.10$/run |
BROWSERLESS_URL + BROWSERLESS_TOKEN | Visual screenshots si Playwright local indispo | ~0.005$/screenshot |
RATE_LIMIT_PER_IP_PER_MINUTE | Hardening (défaut 5) | — |
RATE_LIMIT_PER_IP_PER_HOUR | Hardening (défaut 30) | — |
BUDGET_*_USD_PER_DAY | Circuit breaker quotidien par API (PSI/MOZ/PLACES/OPENROUTER/DATAFORSEO) | — |
ALLOW_LOCALHOST_AUDIT | Bypass SSRF guard pour dev local | — |
Erreurs & rate limits
Codes HTTP
| Code | Cause | Action |
|---|---|---|
400 | Body JSON invalide, URL malformée, SSRF blocked | Vérifier le format du body et l'URL |
429 | Rate limit dépassé (per-minute ou per-hour) | Voir headers Retry-After, X-RateLimit-Reset |
502 | Site cible inaccessible (timeout, DNS, 5xx) | Réessayer, vérifier disponibilité cible |
500 | Erreur serveur interne | Reporter avec le payload |
Format d'erreur
Headers rate limit
Docker / déploiement
Image Docker
Stack
- Next.js 15.5 (App Router) + Turbopack
- TypeScript 5.8 strict
- React 19 + Tailwind CSS 4
- Cheerio 1.0 (parsing HTML)
- Zod 3.24 (validation runtime)
- Vitest 3.2 (108 tests)
- Playwright optionnel (visual capture)