aeo_your_key_here with your own key and any SCAN_ID style placeholder with a real id from the matching list endpoint.Basics
Authentication
Create an API key in your dashboard under Account Settings → API Keys. The full key is shown exactly once at creation. Send it on every request as a Bearer token:
curl "https://aeovilla.com/api/v1/scans" \
-H "Authorization: Bearer aeo_your_key_here"Requests without a valid key return 401. Revoked keys stop working immediately, and keys stop working if the account leaves the agency plan (403).
Basics
Rate limits and versioning
Each key is limited to 60 requests per minute (the limit is set per plan, and every plan with API access shares this limit today); exceeding it returns 429. All endpoints live under /api/v1. Most are read only; scans and site audits can also be triggered with POST. Backward incompatible changes will ship under a new version prefix.
Reference
Endpoints
GET/api/v1/scans
Lists your page scans, newest first. Paginated with ?page= (20 per page).
curl "https://aeovilla.com/api/v1/scans?page=1" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"id": "6a43b1a77c1e0abb32d7c598",
"url": "https://example.com",
"score": 83,
"grade": "Excellent",
"createdAt": "2026-06-30T12:08:07.538Z"
}
],
"page": 1,
"pageSize": 20,
"total": 42
}POST/api/v1/scans
Runs a new page scan for a URL and returns its score, subject to the same monthly scan quota and SSRF safety checks as the dashboard's single scan tool.
curl -X POST "https://aeovilla.com/api/v1/scans" \
-H "Authorization: Bearer aeo_your_key_here" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'{
"data": {
"id": "6a43b1a77c1e0abb32d7c598",
"url": "https://example.com",
"score": 83,
"grade": "Excellent",
"createdAt": "2026-06-30T12:08:07.538Z"
}
}GET/api/v1/scans/:id
Full scan detail: overall score, per category scores, and every flagged issue with its recommendation.
curl "https://aeovilla.com/api/v1/scans/SCAN_ID" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": {
"id": "6a43b1a77c1e0abb32d7c598",
"url": "https://example.com",
"score": 53,
"grade": "Average",
"categories": {
"schema": 30,
"metadata": 40,
"clarity": 70,
"trust": 15,
"aiReadiness": 50,
"performance": 100,
"headings": 100,
"eeat": 25
},
"issues": [
{
"severity": "high",
"category": "Schema",
"title": "Structured Data Missing",
"message": "No JSON-LD structured data found on the page.",
"recommendation": "Add Organization and WebSite schema to the page head."
}
],
"createdAt": "2026-06-30T12:08:07.538Z"
}
}GET/api/v1/audits
Lists your full site crawl audits, newest first. Paginated with ?page= (20 per page).
curl "https://aeovilla.com/api/v1/audits?page=1" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"id": "6a3fa1264b68b30d382013e0",
"domain": "example.com",
"averageScore": 79,
"pagesScanned": 11,
"createdAt": "2026-06-27T10:08:38.998Z"
}
],
"page": 1,
"pageSize": 20,
"total": 3
}GET/api/v1/audits/:id
Full audit detail: every crawled page with its score, the sitewide issue rollup, a keyword cannibalization report, and a diff against the previous crawl of the same domain (when one exists).
curl "https://aeovilla.com/api/v1/audits/AUDIT_ID" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": {
"id": "6a3fa1264b68b30d382013e0",
"domain": "example.com",
"averageScore": 79,
"pagesScanned": 11,
"pages": [
{
"url": "https://example.com/about",
"score": 84,
"grade": "Excellent",
"criticalIssuesCount": 0
}
],
"siteWideIssues": [
{
"category": "Schema",
"count": 4,
"recommendation": "Add FAQPage schema to question and answer pages."
}
],
"previousAuditId": "6a3f72226f364bd3a7ea9401",
"diffSummary": {
"newPages": ["https://example.com/new-guide"],
"removedPages": [],
"changedPages": [
{
"url": "https://example.com/pricing",
"scoreBefore": 72,
"scoreAfter": 84,
"titleChanged": true,
"schemaChanged": false
}
]
},
"cannibalization": [
{
"pages": [
"https://example.com/blog/seo-tips",
"https://example.com/blog/seo-guide"
],
"similarity": 0.82,
"sharedTerms": ["seo", "tips", "guide"],
"recommendation": "These pages appear to target the same topic (seo, tips, guide). Consolidate them into one authoritative page, or differentiate titles and headings so each targets a distinct query."
}
],
"createdAt": "2026-06-27T10:08:38.998Z"
}
}POST/api/v1/audits
Kicks off a new multi page site audit for a domain. The crawl runs in the background exactly like the dashboard's audit trigger. Poll GET /api/v1/audits/:id for progress once status moves from running to completed.
curl -X POST "https://aeovilla.com/api/v1/audits" \
-H "Authorization: Bearer aeo_your_key_here" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'{
"data": {
"id": "6a3fa1264b68b30d382013e0",
"status": "running"
}
}GET/api/v1/monitors
Your monitored URLs with the complete score trend history: every rescan entry includes the overall score and all eight category scores, ready to chart.
curl "https://aeovilla.com/api/v1/monitors" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"id": "6a3f8d2e8f7837d921eeab10",
"url": "https://example.com",
"schedule": "weekly",
"isActive": true,
"lastScanDate": "2026-06-27T08:39:33.065Z",
"nextScanDate": "2026-07-04T08:39:33.065Z",
"history": [
{
"date": "2026-06-27T08:39:33.065Z",
"score": 93,
"categories": {
"schema": 95,
"metadata": 90,
"clarity": 88,
"performance": 100,
"trust": 85,
"aiReadiness": 96,
"headings": 100,
"eeat": 80
}
}
],
"decayFlag": {
"isDecaying": false,
"delta": 0,
"consecutiveDeclines": 0,
"detectedAt": null
},
"createdAt": "2026-06-20T08:39:33.065Z"
}
]
}GET/api/v1/citations
Your tracked AI citation prompts with full check history: citation rate, cited source domains, and competitor hit rates per check, newest last.
curl "https://aeovilla.com/api/v1/citations" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"id": "6a3f95118f7837d921eead02",
"prompt": "best project management tools for agencies",
"targetDomain": "example.com",
"competitors": ["competitor.com"],
"schedule": "weekly",
"lastRunAt": "2026-06-27T09:00:00.000Z",
"nextRunAt": "2026-07-04T09:00:00.000Z",
"history": [
{
"date": "2026-06-27T09:00:00.000Z",
"citationRate": 66,
"citedDomains": ["example.com", "review-site.com"],
"competitorHits": { "competitor.com": 33 }
}
],
"createdAt": "2026-06-20T09:00:00.000Z"
}
]
}GET/api/v1/visibility
Workspace level AI visibility (share of voice) snapshots: brand rate vs named competitor rates, plus average position and sentiment, aggregated across your tracked prompts. Filter with ?period=week or ?period=day.
curl "https://aeovilla.com/api/v1/visibility?period=week" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"week": "2026-W27",
"period": "week",
"brandRate": 58,
"competitorRates": { "competitor.com": 33 },
"avgPosition": 1.4,
"avgSentimentScore": 42,
"sampleSize": 6,
"computedAt": "2026-07-04T08:00:00.000Z"
}
]
}GET/api/v1/prompts
Your saved Prompt Library, newest first. Paginated with ?page= (20 per page).
curl "https://aeovilla.com/api/v1/prompts?page=1" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"id": "6a3f95118f7837d921eead02",
"text": "best project management tools for agencies",
"type": "geo_prompt",
"journeyStage": "consideration",
"tags": ["comparison"],
"source": "user",
"createdAt": "2026-06-20T09:00:00.000Z"
}
],
"page": 1,
"pageSize": 20,
"total": 12
}GET/api/v1/recommendations
Your recommendations queue, highest priority first. Filter with ?status= (open, in_progress, done, or dismissed). Paginated with ?page= (20 per page).
curl "https://aeovilla.com/api/v1/recommendations?status=open" \
-H "Authorization: Bearer aeo_your_key_here"{
"data": [
{
"id": "6a3fb2118f7837d921eeafa1",
"type": "on_page_fix",
"source": "scan_issue",
"title": "Structured Data Missing",
"description": "Add Organization and WebSite schema to the page head.",
"priorityScore": 90,
"priorityLabel": "critical",
"status": "open",
"assignee": null,
"createdAt": "2026-06-30T12:08:07.538Z"
}
],
"page": 1,
"pageSize": 20,
"total": 7
}Exports
CSV exports
Every major data table in the dashboard (scans, site audits, monitors, the Prompt Library, recommendations, and cited domains) has an "Export CSV" download next to its list. It is session authenticated, not part of the API key surface above. Useful for a quick spreadsheet pull without writing any code against the endpoints documented here.
Tooling
MCP server
AEO Villa also runs a hosted Model Context Protocol server at https://aeovilla.com/api/mcp, so an AI assistant can query and act on your AEO data directly instead of you copying numbers into a prompt by hand. It speaks Streamable HTTP and uses the exact same API key as the REST endpoints above. Configure your MCP client to send Authorization: Bearer aeo_your_key_here as a custom header on every request to that URL.
Available tools:
list_scans,run_scanlist_audits,run_auditget_visibilitylist_recommendationsget_citations
Most MCP compatible clients and AI assistants read their servers from a JSON config file. Add an entry like this one to yours:
{
"mcpServers": {
"aeo-villa": {
"url": "https://aeovilla.com/api/mcp",
"headers": {
"Authorization": "Bearer aeo_your_key_here"
}
}
}
}Events
Outbound webhook events
Alongside the read API, AEO Villa can push events to a webhook URL you configure on the AEO Monitoring page. Every event is a JSON POST with a flat payload: { "event": "…", …, "sentAt": "…" }. Point the URL at Zapier, Make, or your own endpoint to turn flagged issues into tasks in any project management or CRM tool, with no per tool connector needed.
issue_flagged
Fires when a scan or site audit finds critical issues. Site audits send auditId and domain instead of scanId and url.
{
"event": "issue_flagged",
"scanId": "6a43b1a77c1e0abb32d7c598",
"url": "https://example.com",
"score": 53,
"criticalCount": 2,
"issues": [
{ "category": "Schema", "title": "Structured Data Missing" }
],
"sentAt": "2026-07-02T10:00:00.000Z"
}score_drop
Fires when a monitored URL falls 10 or more points between rescans.
{
"event": "score_drop",
"url": "https://example.com",
"oldScore": 82,
"newScore": 64,
"drop": 18,
"date": "2026-07-02T10:00:00.000Z",
"sentAt": "2026-07-02T10:00:00.000Z"
}citation_change
Fires when a tracked prompt's citation rate moves 25 or more points between scheduled checks.
{
"event": "citation_change",
"prompt": "best project management tools for agencies",
"targetDomain": "example.com",
"oldRate": 66,
"newRate": 0,
"date": "2026-07-02T10:00:00.000Z",
"sentAt": "2026-07-02T10:00:00.000Z"
}report_ready
Fires when a scheduled client report is generated for a monitored URL.
{
"event": "report_ready",
"url": "https://example.com",
"score": 78,
"reportUrl": "https://aeovilla.com/r/abc123def456",
"date": "2026-07-02T10:00:00.000Z",
"sentAt": "2026-07-02T10:00:00.000Z"
}anomaly_detected
Fires on a statistically unusual score or citation rate movement that doesn't cross the fixed score_drop/citation_change thresholds: a spike, or several consecutive declines in a row.
{
"event": "anomaly_detected",
"url": "https://example.com",
"kind": "spike",
"detail": "Score moved to 91, 2.8 standard deviations from its recent average.",
"date": "2026-07-02T10:00:00.000Z",
"sentAt": "2026-07-02T10:00:00.000Z"
}visibility_drop
Fires when your overall AI visibility (the workspace level share of voice across every tracked prompt, not a single prompt) falls 15 or more points day over day.
{
"event": "visibility_drop",
"oldRate": 62,
"newRate": 40,
"date": "2026-07-02T10:00:00.000Z",
"sentAt": "2026-07-02T10:00:00.000Z"
}new_citation
Fires the first time a tracked prompt goes from never being cited to actually being cited. It is a meaningful transition even when the move is smaller than citation_change's 25 point threshold.
{
"event": "new_citation",
"prompt": "best project management tools for agencies",
"targetDomain": "example.com",
"newRate": 15,
"date": "2026-07-02T10:00:00.000Z",
"sentAt": "2026-07-02T10:00:00.000Z"
}recommendation_status
Fires when a recommendation's status changes (e.g. moved to in_progress or done on the Recommendations board).
{
"event": "recommendation_status",
"recommendationId": "6a3fb2118f7837d921eeafa1",
"title": "Structured Data Missing",
"oldStatus": "open",
"newStatus": "in_progress",
"sentAt": "2026-07-02T10:00:00.000Z"
}Reference
Errors
Errors return a JSON body with an error message and an appropriate status code: 401 invalid or revoked key, 403 plan does not include API access, 404 resource not found or not yours, 429 rate limit exceeded.
{
"error": "Invalid or revoked API key."
}