One-line verdict: The exact engine behind our free AEO Readiness Check, offered as a JSON API — send a domain, get back the full audit: a 0–100 readiness score, the four section scores, all 24 checks with the evidence found for each, and a fix list ranked by points recoverable. No lighter “API version” of the audit — same crawl, same rubric, same honesty label.
Agencies, freelancers, and web builders who check sites in batches — a client roster, a prospect list, a portfolio after a redesign. If you only need one site, the free checker runs this same audit in your browser, with the full visual report. The API is for when you’re doing it fifty times a month and want the result inside your own spreadsheet, CRM, or reporting pipeline.
Base URL: https://altapointdevelopment.com/wp-json/aeocheck/v1
| Method & path | What it does |
|---|---|
POST /check or GET /check?url=… |
Runs the audit for one domain (or returns its 24-hour cached result) and returns the full result as JSON. |
GET /usage |
Returns your key’s quota, calls used this month, and totals — so your pipeline can check itself before we have to tell it no. |
Authentication. Every request carries your key in the X-API-Key header (Authorization: Bearer … works too). Keys look like aeo_live_… and are stored on our side only as hashes — if you lose one, we revoke it and mint a new one; nobody, including us, can recover the original. A missing, wrong, or revoked key returns 401.
Machine-readable contract: the OpenAPI 3.1 spec (JSON) describes both endpoints, the full result schema, and every error code — point your client generator or your AI tooling at it directly.
curl -X POST "https://altapointdevelopment.com/wp-json/aeocheck/v1/check" \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "benjaminfranklinplumbing.com"}'
The url field takes a bare domain or a full homepage URL — paths are ignored, because the homepage is the crawl’s front door, exactly like the web checker.
A real response from this API, produced on November 1, 2026 for a national plumbing franchise’s site — trimmed here to 3 of the 24 checks and 2 of the fixes; everything shown is verbatim. One note: the usage block always reflects your key — this call ran on a small test key, which is why its monthly quota shows 3. An early-access key shows 100.
{
"ok": true,
"domain": "www.benjaminfranklinplumbing.com",
"url_checked": "https://www.benjaminfranklinplumbing.com/",
"final_url": "https://www.benjaminfranklinplumbing.com/",
"score": 84,
"max_score": 100,
"rubric": "AEO Score v2",
"label": "Readiness score from on-site signals \u2014 not a measurement of live ChatGPT / Perplexity / Google AI answers.",
"cached": false,
"checked_at": "Nov 1, 2026, 11:04 PM",
"served_at": "2026-11-01T23:04:39+00:00",
"report_url": "https://altapointdevelopment.com/aeo-check/r/1ab4cd7f29552e63d32d/",
"scope": {
"pages_checked": 10,
"pages": [
{
"label": "Homepage",
"url": "https://www.benjaminfranklinplumbing.com/"
},
{
"label": "FAQ",
"url": "https://www.benjaminfranklinplumbing.com/faq/"
},
{
"label": "FAQ",
"url": "https://www.benjaminfranklinplumbing.com/andover/about-us/faq/"
}
],
"crawl": {
"candidates": 4173,
"attempted": 10,
"missed": [],
"files": {
"robots_status": 200,
"sitemap_at": "/sitemap.xml",
"sitemap_pages": 5625,
"llms_status": 200
}
}
},
"sections": {
"schema": {
"label": "Machine identity & schema",
"points": 21,
"max": 28
},
"machine": {
"label": "Crawler & machine files",
"points": 20,
"max": 20
},
"content": {
"label": "Extractable content",
"points": 30,
"max": 30
},
"local": {
"label": "Local proof & contact",
"points": 13,
"max": 22
}
},
"checks": [
{
"section": "schema",
"id": "jsonld_present",
"label": "JSON-LD structured data present",
"max": 4,
"points": 4,
"status": "pass",
"evidence": "26 JSON-LD blocks found across the checked pages; readable structured data parsed on 10 of the 10 pages.",
"fix": ""
},
{
"section": "schema",
"id": "entity_type",
"label": "Business type named specifically",
"max": 6,
"points": 6,
"status": "pass",
"evidence": "Schema names the business as Plumber \u2014 a specific business type, not a generic entity.",
"fix": ""
},
{
"section": "schema",
"id": "field_completeness",
"label": "Schema field completeness",
"max": 8,
"points": 7,
"status": "partial",
"evidence": "The business schema carries 7 of 8 key fields (name, phone, street address, URL, profile links (sameAs), opening hours, geo coordinates) \u2014 missing: service area.",
"fix": "Add the missing fields to the business schema: service area."
}
// … 21 more checks (24 total)
],
"fixes": [
{
"check": "Service schema",
"points": 3,
"found": "No Service schema found \u2014 services are described only in page text.",
"action": "Add Service schema for each core service, tied to the business and its service area.",
"difficulty": "Quick fix"
},
{
"check": "Review / rating schema",
"points": 3,
"found": "No AggregateRating or Review schema found on any checked page.",
"action": "Once real reviews are published on the site, mark them up with Review / AggregateRating schema that matches them exactly.",
"difficulty": "Quick fix"
}
// … remaining fixes, ranked by points recoverable
],
"usage": {
"requests_this_month": 1,
"monthly_quota": 3,
"remaining": 2
}
}
| Field | Meaning |
|---|---|
score / max_score |
The readiness score out of 100, on the AEO Score v2 rubric — the same rubric the web checker publishes. |
sections |
The four section scores: Machine identity & schema (28), Crawler & machine files (20), Extractable content (30), Local proof & contact (22). |
checks |
All 24 checks, each with points, max, status (pass / partial / fail), the evidence the crawler actually found, and the fix when points were left on the table. |
fixes |
Every check that lost points, re-ranked by points recoverable, with the found evidence, the action, and a rough difficulty (Quick fix / Half-day / Build). |
scope |
How many pages were crawled (up to 10), which ones, and the crawl facts — including any pages that could not be read. An unreadable page is reported, never silently scored as a pass. |
report_url |
The shareable visual report for this check — the same report page the web checker produces. |
cached |
true when the result came from the 24-hour per-domain cache instead of a fresh crawl. |
usage |
Your key’s calls this month, monthly quota, and remaining calls, after this request. |
Errors return {"ok": false, "error": {"code": …, "message": …}} with one of these HTTP statuses:
| Status | Code | What it means |
|---|---|---|
| 400 | aeocheck_invalid_url |
The url value doesn’t look like a website address. |
| 401 | aeocheck_missing_key · aeocheck_invalid_key · aeocheck_key_inactive |
No key sent, the key isn’t recognized, or the key has been revoked. |
| 422 | aeocheck_site_blocked |
The site blocks automated checks (bot protection). No score is issued — a partial crawl would be an unfair verdict, so we don’t fake one. |
| 429 | aeocheck_rate_limited |
Your key passed its per-minute burst limit (10 requests/minute by default). Back off for a minute; a Retry-After header is included. |
| 429 | aeocheck_quota_exceeded |
Your key used its monthly quota. Quotas reset on the 1st of the month. |
| 502 | aeocheck_site_unreachable |
The site itself could not be reached at all. |
Two limits, both per key: a burst limit (10 requests per minute by default — a fresh crawl takes 10–25 seconds anyway, so this only bites scripts firing cached lookups in a loop) and a monthly quota. During early access, a free key carries 100 requests a month. If you need more, request a key and tell us your volume — higher quotas are set per key.
How counting works, stated plainly: a request counts once toward your monthly quota when it is served — including results served from the cache and sites that turn out to be blocked or unreachable (the crawl still ran). Requests rejected for a bad key or for exceeding a limit never count.
The 24-hour cache is the same one the web checker uses: the first check of a domain crawls up to 10 pages; any check of that domain in the next 24 hours returns the stored result in about a second, with "cached": true in the response and cached also shown in the X-AEO-Cache header (hit / miss). Scores never go silently stale — the flag is always there, and checked_at tells you when the crawl actually happened.
This is a readiness score from on-site signals — schema, extractable Q&A, contact details, service pages, reviews, and machine files. It is not a measurement of live ChatGPT, Perplexity, or Google AI answers, and it never claims to be: the same label travels inside every API response (label). It measures whether a site publishes what answer engines rely on when they choose what to cite. Sites behind bot protection get a 422 and no score, because an incomplete crawl scored as fact would be worse than no number at all.
Keys are minted by hand during early access — free tier, 100 requests a month, no card and no self-serve signup form. Tell us your agency or studio name and roughly how many sites you check a month, and we’ll issue a key sized to it.
One site, one time? Skip the key — the free AEO Checker runs the identical audit in your browser.