AnswerSEO
FeaturesPricingBlog
Sign inStart free audit

REST API

Last updated: June 17, 2026 · SG Systems PTE. LTD.

The AnswerSEO REST API gives Studio-plan accounts programmatic access to scans and Citation Readiness data. All endpoints are JSON in / JSON out, mounted under /api/v1, and authenticated with a Bearer token minted from your dashboard.

Plan requirement

API access is gated on the Studio plan. Free and Pro accounts can view this reference but cannot mint tokens. See pricing for details.

Authentication

Mint a token at /dashboard/account/tokens. The plaintext is shown once at creation; only its SHA-256 hash is stored. Pass it in the Authorization header on every request:

Authorization: Bearer asr_live_<your token>

Tokens are full-account today (no per-token scopes yet). A downgrade from Studio revokes API access on the next request — existing tokens are not deleted, just rejected with 402 plan_required until the plan is restored.

Rate limits

  • POST /api/v1/scan — 10 requests per minute per token.
  • Read endpoints (GET /scan/:id, GET /projects/:id/readiness) — 120 requests per minute per token, shared bucket.

Over-limit responses return HTTP 429 with a Retry-After header (seconds).

Errors

All errors return JSON of shape { error, message? }.

HTTPerrorWhen
401unauthorizedMissing or malformed Authorization header.
401invalid_tokenToken not recognised or revoked.
402plan_requiredAccount is not on the Studio plan.
402quota_exceededMonthly credit limit reached.
402domain_limitPlan's active-domain allowance reached.
404not_foundResource not found or not owned by your account (we don't leak existence across users).
409scan_in_progressThe project already has a queued/running scan.
409duplicate_domainAnother active project on the same account uses this domain.
422invalid_bodyBody failed schema validation. issues array is included.
429rate_limitedPer-token rate limit exceeded.

Endpoints

POST /api/v1/scan

Kick off a scan for one of your projects. The pipeline runs detached; poll the scan-status endpoint to track progress.

Body: { "projectId"?: string }. Omit projectId and the newest project on the account is used.

Success: 202 { "scanId": "...", "status": "queued" }.

curl -X POST https://answerseo.app/api/v1/scan \
  -H "Authorization: Bearer asr_live_..." \
  -H "Content-Type: application/json" \
  -d '{"projectId":"clx..."}'

GET /api/v1/scan/:id

Poll scan status. Returns 404 if the scan does not exist or is not owned by the token's account.

curl https://answerseo.app/api/v1/scan/clx... \
  -H "Authorization: Bearer asr_live_..."

{
  "id": "clx...",
  "projectId": "clx...",
  "status": "running",
  "step": 4,
  "visibilityScore": null,
  "startedAt": "2026-06-17T22:30:14.000Z",
  "finishedAt": null,
  "lastHeartbeatAt": "2026-06-17T22:33:02.000Z",
  "error": null
}

GET /api/v1/projects/:id/readiness

Returns per-prompt Citation Readiness from the project's most recent completed scan. Rows are produced during the scan — no recompute on read. Returns 404 no_completed_scan if no completed scan exists yet.

Per-row signals (each 0–100):

  • answer — answer-first surface area.
  • evidence — stats / quotes / authoritative outbound links.
  • structure — main-content formatting density.
  • fresh — recency of the page's modified date.
  • retrieve — GSC rank + AI-crawler allow + off-page authority proxy.
curl https://answerseo.app/api/v1/projects/clx.../readiness \
  -H "Authorization: Bearer asr_live_..."

{
  "projectId": "clx...",
  "scanId": "clx...",
  "scoredAt": "2026-06-17T22:42:01.000Z",
  "composite": 71,
  "rows": [{
    "promptId": "clx...",
    "promptText": "best AI dubbing for podcasters",
    "url": "https://yoursite.com/dubbing",
    "competitorUrl": "https://competitor.com/dubbing",
    "competitorHost": "competitor.com",
    "matchType": "page",
    "you":  { "readiness": 71, "signals": {"answer":80,"evidence":62,"structure":55,"fresh":90,"retrieve":70}, "freshDate": "2026-06-12" },
    "them": { "readiness": 64, "signals": {"answer":70,"evidence":58,"structure":60,"fresh":40,"retrieve":80}, "freshDate": "2026-04-02" },
    "gap": 7,
    "fixes": ["Add an answer-first H2 within the first 30% of the page", "..."]
  }]
}

Webhooks

Register an https endpoint at /dashboard/account/webhooks to receive a signed POST whenever a scan completes or fails. Studio plan required.

Events

  • scan.completed — fired after a scan reaches status: "done". Payload includes id, projectId, visibilityScore, finishedAt.
  • scan.failed — fired when a scan terminates in status: "failed". Payload includes id, projectId, error, currentStep, finishedAt.

Headers

  • Content-Type: application/json
  • User-Agent: AnswerSEO-Webhook/1
  • X-Answerseo-Event: scan.completed (or scan.failed / webhook.test)
  • X-Answerseo-Signature: t=<unix seconds>,v1=<hex>

Verify the signature (Node.js)

import crypto from "node:crypto"

const SECRET = process.env.ANSWERSEO_WEBHOOK_SECRET  // whsec_...

export function verify(rawBody, sigHeader) {
  const m = /^t=(\d+),v1=([0-9a-f]+)$/.exec(sigHeader ?? "")
  if (!m) return false
  const [, t, v1] = m
  const mac = crypto.createHmac("sha256", SECRET)
                    .update(`${t}.${rawBody}`)
                    .digest("hex")
  // Constant-time compare so timing leaks don't expose the secret.
  const ok = crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(v1))
  // ±5-minute replay window.
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300
  return ok && fresh
}

Verify the signature (Python)

import hmac, hashlib, os, re, time

SECRET = os.environ["ANSWERSEO_WEBHOOK_SECRET"]

def verify(raw_body: bytes, sig_header: str) -> bool:
    m = re.match(r"^t=(\d+),v1=([0-9a-f]+)$", sig_header or "")
    if not m: return False
    t, v1 = m.group(1), m.group(2)
    mac = hmac.new(SECRET.encode(), f"{t}.{raw_body.decode()}".encode(),
                   hashlib.sha256).hexdigest()
    if not hmac.compare_digest(mac, v1): return False
    return abs(time.time() - int(t)) < 300

Retries

We retry up to 3 times per delivery with exponential backoff (~0.5s / 1s / 2s). After 10 consecutive failures (5xx, timeouts, or unreachable hosts) the endpoint is auto-paused. Re-register or contact info@answerseo.app to reactivate.

Versioning

The current version is v1. Breaking changes will ship under a new /api/v2 prefix; v1 stays supported for at least 12 months after a successor is announced.

Coming next

  • Per-token scopes.
  • OpenAPI spec.
  • Per-delivery audit log + replay-from-dashboard.

Hit a wall? Email info@answerseo.app.

AnswerSEO
The AEO platform for indie founders. Track and improve how AI engines talk about your brand.
Made in Singapore

Product

FeaturesPricingChangelog

Resources

BlogAEO guidellms.txt specSchema cheatsheetREST API

Company

AboutTermsPrivacyDPA
© 2026 SG Systems PTE. LTD. All rights reserved.