API REFERENCE

AEOlens API

Endpoint reference for programmatic AEOlens access — public (no-auth) scan endpoints, CI/CD scan-and-gate, plus the authenticated dashboard endpoints. Base URL: https://aeolens.ai

Last updated 2026-06-06

Authentication

Three authentication modes are in use across the API:

  • No auth
    Public quick-scan endpoints under /api/public/… — rate-limited per IP, no headers required.
  • Session (JWT)
    Dashboard endpoints use Supabase JWTs in the Authorization: Bearer eyJ… header. Used by the web app; CLI tools should prefer API keys.
  • API key
    CI/CD and programmatic endpoints accept a long-lived aeol_… token via Authorization: Bearer aeol_…. Create one at Settings → API keys. The raw token is shown once at creation time — store it in your CI provider's secret manager.

Public scan (no auth)

The endpoints powering the homepage hero. No headers required. Rate-limited at 10 scans / hour / IP.

POST/api/public/quick-scan

Trigger a partial public scan

No auth required
Kicks off a no-auth scan against a URL. Returns immediately with a token; the actual scan runs in the background and the partial result is available via the GET endpoint below within ~5–15 seconds.
Request body
FieldTypeRequiredDescription
urlstringrequiredPublic HTTPS URL to scan. Private/loopback addresses are rejected.
Example
curl -X POST https://aeolens.ai/api/public/quick-scan \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'
Responses
  • 202Scan accepted. Returns { token, status: "running" }.
  • 400Invalid URL (bad scheme or resolves to a private IP).
  • 429Hourly per-IP rate limit exceeded.
  • 503Backing services temporarily unavailable.
GET/api/public/quick-scan/{token}

Read a public scan by token

No auth required
Returns the scan's current state. Poll while status: "running"; stop when it reaches "done" or "failed". Tokens expire after 30 days.
Example
curl https://aeolens.ai/api/public/quick-scan/abc123def456
Responses
  • 200Returns { token, status, score?, category_scores?, failing_checks?, … }.
  • 404Unknown or expired token.

CI/CD scan-and-gate

Synchronous endpoint designed for deployment pipelines. Returns a passed: true | false body the caller can branch on. See the full integration guide at /docs/ci-cd.

POST/api/v1/ci/scan

Run a scan synchronously and return pass/fail

API key (Bearer aeol_…)
Queues a scan, polls until terminal or max_wait_seconds elapses, returns the result. Always returns 200 on a successful HTTP exchange — the deploy decision is the passed field. Requires Growth or Agency plan.
Request body
FieldTypeRequiredDescription
urlstringrequiredURL to scan (typically a staging or just-deployed URL).
min_scoreint (0–100)optionalThreshold for passed=true. Default 70.
max_wait_secondsint (10–300)optionalHow long to wait synchronously. Default 180.
Example
curl -X POST https://aeolens.ai/api/v1/ci/scan \
  -H "Authorization: Bearer $AEOLENS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://staging.example.com","min_score":70}'
Responses
  • 200Returns { status, passed, score, threshold, scan_id, scan_url, failed_checks, … }.
  • 400Your workspace has no projects yet.
  • 401Missing, invalid, or revoked API key.
  • 402Plan quota exceeded.
  • 503Scan queue unavailable; retry shortly.

Selected authenticated endpoints

These run under session auth today but accept the same JWT pattern any caller can use. Full surface area is broader; the dashboard SWR helpers wrap each. Email contact@aeolens.ai if you need API-key support on a specific endpoint and we'll prioritise it.

POST/api/scans

Start a scan from the dashboard

Session (dashboard JWT)
Triggers a full 48-check scan against a project URL. Counts against the workspace's monthly scan quota.
Request body
FieldTypeRequiredDescription
urlstringrequiredPublic URL to scan.
project_idstringrequiredWorkspace project to associate the scan with.
Responses
  • 202Scan queued. Returns { scan_id, status: "queued" }.
  • 402Workspace scan quota exhausted.
  • 429Hourly per-user rate limit exceeded.
GET/api/scans/{scan_id}

Read a completed scan

Session (dashboard JWT)
Returns the scan row with score, struct_data, pages_scanned, CMS detection, and signed report URL.
Responses
  • 200Returns the scan payload.
  • 404Scan not found or not accessible by this user.
POST/api/scans/{scan_id}/audit-storm

Generate Audit Storm post captions

Session (dashboard JWT)
Returns ready-to-paste X + LinkedIn captions for a completed scan, plus a meta block (domain, score, top failing checks). The accompanying image is the share-card endpoint.
Responses
  • 200Returns { caption_x, caption_linkedin, meta }.
  • 404Scan not found.
POST/api/simulations/results/{result_id}/why-not-cited

Per-query "why AI didn't cite us" diagnosis

Session (dashboard JWT)
Lazy LLM-powered diagnosis for an uncited simulation result row. Cached on the row so re-opens return instantly.
Responses
  • 200Returns { diagnosis: { summary, reasons, suggestions }, cached: bool }.
  • 400Simulation not done, or the row was actually cited.
  • 502LLM error; retry.
POST/api/simulations/{simulation_id}/content-brief

Generate a structured content brief

Session (dashboard JWT)
LLM-powered brief for a content gap surfaced by the simulation. Returns target query, slug, H1, meta, outline, entities, FAQ, schema recommendation.
Request body
FieldTypeRequiredDescription
gapstringrequiredThe gap text the brief should close.
affected_queriesstring[]optionalBuyer queries this brief should serve.
Responses
  • 200Returns { brief: { target_query, slug, h1, meta_description, outline, target_word_count, entities_to_cover, faq_questions, internal_links, schema_recommendation } }.
  • 502Brief model error or insufficient content.
GET/api/settings/organization/{org_id}/branding

Read white-label branding

Session (dashboard JWT)
Agency-plan only. Returns the current white-label logo URL and brand name for the org. Used by exports.
Responses
  • 200Returns { white_label_logo_url, white_label_brand_name }.
  • 403Branding requires Agency plan.
PATCH/api/settings/organization/{org_id}/branding

Update white-label branding

Session (dashboard JWT)
Owner role + Agency plan required. Pass null on either field to clear it.
Request body
FieldTypeRequiredDescription
white_label_logo_urlstring | nulloptionalPublic HTTPS URL of the logo.
white_label_brand_namestring | nulloptionalBrand name for export headers.
Responses
  • 200Returns the updated branding object.
  • 403Requires Agency plan + owner role.
  • 422Invalid URL format on white_label_logo_url.

Error responses

JSON error bodies follow one of two shapes depending on the endpoint:

FastAPI default
{
  "detail": "Human-readable message"
}
Quota / rate-limit shape
{
  "error": "rate_limit_exceeded",
  "message": "…",
  "limit": 10,
  "retry_after": "3600"
}

All responses include an X-Request-ID header. Include that in any support email and we can correlate to backend logs.

Need an endpoint that's not here?

The dashboard surfaces hundreds of endpoints. If you want API-key support on a specific one, email us — we move quickly on real customer requests.

Email API team