v1Resources/AEO

AEO

Track a location's visibility in AI answer engines (ChatGPT, Gemini, Perplexity): how often it's mentioned, where it ranks against competitors, and what's holding its score back.

Returns the latest AI-visibility report for a location: overall and per-engine scores, the keyword/prompt matrix, competitor gap and ranking comparisons, citation coverage, sentiment, and recommended fixes. Report generation is asynchronous — this is also the poll target for POST /api/v1/aeo/reports/enqueue: keep calling this endpoint and watch the generating field until it flips back to false and generatedAt updates. Pass prompt to drill into one tracked prompt instead of the full report.

Get a location's AEO report

get/api/v1/aeo/reports
aeo:read
Query parameters
locationIdstringrequired
The location to look up.
clientIdstringoptional
The location's client.
promptstringoptional
Drill into one tracked prompt (matched case-insensitively) instead of returning the full report. Returns null cells if the prompt isn't in this location's matrix.
Response
dataobjectoptional
Errors
400The request is missing a required parameter or is otherwise malformed.
401Missing, invalid, expired, or revoked API key.
403The key lacks the required scope, or isn't authorized for this client/location.
404The resource wasn't found, or doesn't belong to your agency.
429Too many requests. Retry after the number of seconds in the Retry-After header.
get/api/v1/aeo/reports
Your API key
locationId *
clientId
prompt
{
  "data": {
    "generatedAt": "2026-02-01T06:00:00.000Z",
    "generating": false,
    "configuredEngines": [
      "ChatGPT",
      "Gemini"
    ],
    "visibility": {
      "overall": 62,
      "label": "GOOD",
      "message": "Your business shows up for most of the prompts you're tracking.",
      "engines": {
        "ChatGPT": {
          "score": 68,
          "comparisonPct": 12,
          "configured": true
        },
        "Gemini": {
          "score": 56,
          "comparisonPct": -4,
          "configured": true
        },
        "Perplexity": {
          "score": null,
          "comparisonPct": null,
          "configured": false
        }
      }
    },
    "metrics": {
      "visibility": {
        "value": 62,
        "delta": 5
      },
      "mentionRate": {
        "value": 71,
        "delta": 3
      },
      "avgPosition": {
        "value": 2.1,
        "delta": -0.4
      },
      "promptsCovered": {
        "value": 8,
        "total": 10
      },
      "sourcesCited": {
        "value": 14,
        "delta": 2
      }
    },
    "keywordMap": {
      "ChatGPT": [
        {
          "keyword": "best dentist austin",
          "percentage": 82,
          "dataSources": [
            {
              "name": "Google Business Profile"
            }
          ]
        }
      ],
      "Gemini": [
        {
          "keyword": "emergency dentist austin",
          "percentage": 54,
          "dataSources": []
        }
      ],
      "Perplexity": []
    },
    "matrix": [
      {
        "keyword": "best dentist austin",
        "cells": {
          "ChatGPT": {
            "score": 82,
            "mentioned": true,
            "rank": 1,
            "answerExcerpt": "Acme Dental — Downtown is highly rated for..."
          },
          "Gemini": {
            "score": 54,
            "mentioned": true,
            "rank": 3,
            "answerExcerpt": null
          },
          "Perplexity": null
        },
        "best": 82
      }
    ],
    "gap": [
      {
        "business": "Acme Dental — Downtown",
        "isYou": true,
        "overall": 62,
        "chatgpt": 68,
        "gemini": 56,
        "perplexity": null,
        "comparisonPct": null
      },
      {
        "business": "Smile Bright Dental",
        "isYou": false,
        "overall": 71,
        "chatgpt": 74,
        "gemini": 68,
        "perplexity": null,
        "comparisonPct": 9
      }
    ],
    "ranking": {
      "All": {
        "primary": {
          "good": 6,
          "neutral": 2,
          "bad": 2
        },
        "competitors": []
      },
      "ChatGPT": {
        "primary": {
          "good": 7,
          "neutral": 1,
          "bad": 2
        },
        "competitors": []
      },
      "Gemini": {
        "primary": {
          "good": 5,
          "neutral": 3,
          "bad": 2
        },
        "competitors": []
      },
      "Perplexity": {
        "primary": {
          "good": 0,
          "neutral": 0,
          "bad": 0
        },
        "competitors": []
      }
    },
    "radar": {
      "ChatGPT": {
        "relevance": 78,
        "reviews": 88,
        "engagement": 65,
        "freshness": 74,
        "citations": 81
      },
      "Gemini": {
        "relevance": 70,
        "reviews": 80,
        "engagement": 75,
        "freshness": 85,
        "citations": 65
      },
      "Perplexity": {
        "relevance": 0,
        "reviews": 0,
        "engagement": 0,
        "freshness": 0,
        "citations": 0
      }
    },
    "factors": [
      {
        "key": "citations",
        "label": "Citations",
        "value": 81,
        "detail": "Cited by 14 of 20 tracked sources across configured engines.",
        "action": {
          "label": "Fix missing citations",
          "target": "citations"
        }
      }
    ],
    "citations": {
      "summary": {
        "totalSources": 20,
        "active": 14,
        "detected": 4,
        "missing": 2,
        "missingDirectories": [
          "Yelp"
        ]
      },
      "byEngine": {
        "ChatGPT": [
          {
            "name": "Google Business Profile",
            "status": "active"
          }
        ],
        "Gemini": [],
        "Perplexity": []
      }
    },
    "sentiment": {
      "positive": 62,
      "neutral": 30,
      "negative": 8,
      "mentions": []
    },
    "attention": [
      {
        "text": "Bing Places is missing your current hours.",
        "tone": "warn"
      }
    ],
    "recommendations": [
      {
        "id": "rec_reviews_1",
        "kind": "opportunity",
        "priority": "high",
        "title": "Add more customer reviews mentioning services",
        "detail": "Reviews that name specific services improve how often engines cite you for those prompts.",
        "action": {
          "label": "Request reviews",
          "target": "reviews"
        }
      }
    ],
    "history": [
      {
        "yearMonth": "2026-01",
        "overall": 57,
        "chatgpt": 61,
        "gemini": 53,
        "perplexity": null,
        "sources": 12
      },
      {
        "yearMonth": "2026-02",
        "overall": 62,
        "chatgpt": 68,
        "gemini": 56,
        "perplexity": null,
        "sources": 14
      }
    ],
    "competitorHistory": [
      {
        "name": "Smile Bright Dental",
        "points": [
          {
            "yearMonth": "2026-01",
            "overall": 65
          },
          {
            "yearMonth": "2026-02",
            "overall": 71
          }
        ]
      }
    ]
  }
}
v1Resources/AEO/postEnqueue AEO report generation

Starts a background generation of a fresh AEO report for a location. Report generation runs multiple LLM calls per engine/prompt and never runs synchronously in-request — this call enqueues the job and returns immediately. There is no separate job-id or status resource: poll GET /api/v1/aeo/reports for the same location and watch the generating field until it returns to false. Not available for locations that predate Synup's legacy location cache (native-only locations).

Enqueue AEO report generation

post/api/v1/aeo/reports/enqueue
aeo:write
Request body
locationIdstringrequired
The location to generate a report for.
clientIdstringoptional
The location's client.
forcebooleanoptional
When true, starts a fresh generation even if a report was already generated this month.
Response
dataobjectoptional
enqueuedbooleanoptional
Always true — the generation job was enqueued.
forcebooleanoptional
Echoes back the force flag from the request.
Errors
400The request is missing a required parameter or is otherwise malformed.
401Missing, invalid, expired, or revoked API key.
403The key lacks the required scope, or isn't authorized for this client/location.
404The resource wasn't found, or doesn't belong to your agency.
429Too many requests. Retry after the number of seconds in the Retry-After header.
post/api/v1/aeo/reports/enqueue
Your API key
Request body*
{
  "data": {
    "enqueued": true,
    "force": false
  }
}
v1Resources/AEO/getGet the all-locations AEO roll-up

Returns the latest AEO report summary per location, optionally scoped to a client and/or location tags, plus portfolio-wide trend and systemic-fix data. Locations with no report yet show null scores.

Get the all-locations AEO roll-up

get/api/v1/aeo/rollup
aeo:read
Query parameters
clientIdstringoptional
Restrict results to one client. When your key is scoped to specific clients, this is required.
tagsstringoptional
Comma-separated location tag names. Only locations carrying at least one of these tags are included.
Response
dataobjectoptional
rowsarray of objectoptional
One row per in-scope location.
locationIdstringoptional
Unique identifier for the location.
namestringoptional
The location's business name.
citystringoptional
City, or null.
overallnumberoptional
Latest overall AI-visibility score (0-100), or null if never generated.
chatgptnumberoptional
Latest ChatGPT score, or null.
gemininumberoptional
Latest Gemini score, or null.
perplexitynumberoptional
Latest Perplexity score, or null.
generatedAtstringoptional
When the latest report was generated, as an ISO 8601 timestamp, or null if never generated.
yearMonthstringoptional
Month of the latest report (YYYY-MM), or null.
tagsarray of stringoptional
The location's internal tags.
historyarray of numberoptional
Overall-score history for this location, chronological, non-null values only.
deltanumberoptional
Overall-score change vs the previous report, or null on the first report or if there's no prior month.
topIssueobjectoptional
This location's weakest visibility factor, or null if it has no report yet.
labelstringoptional
tonestring (good | warn | bad)optional
configuredEnginesarray of string (ChatGPT | Gemini | Perplexity)optional
AI engines this agency has an API key configured for.
portfolioHistoryarray of objectoptional
Average overall score across in-scope locations, per month.
yearMonthstringoptional
Month in YYYY-MM form.
avgnumberoptional
Average overall score across reporting locations that month.
locationsnumberoptional
Number of locations with a report that month (the average's denominator).
systemicFixesarray of objectoptional
Cross-location weaknesses shared by multiple locations, each with a single batch fix, ranked by reach.
factorstringoptional
Machine-readable factor identifier.
labelstringoptional
Human-readable factor name.
detailstringoptional
Explanation of the systemic weakness.
targetstring (listings | citations | reviews | posts | competitors | prompts)optional
Which part of the product the fix routes to.
countnumberoptional
Number of locations affected.
pctnumberoptional
Percent of reporting locations affected.
Errors
401Missing, invalid, expired, or revoked API key.
403The key lacks the required scope, or isn't authorized for this client/location.
429Too many requests. Retry after the number of seconds in the Retry-After header.
get/api/v1/aeo/rollup
Your API key
clientId
tags
{
  "data": {
    "rows": [
      {
        "locationId": "cm_loc_1",
        "name": "Acme Dental — Downtown",
        "city": "Austin",
        "overall": 62,
        "chatgpt": 68,
        "gemini": 56,
        "perplexity": null,
        "generatedAt": "2026-02-01T06:00:00.000Z",
        "yearMonth": "2026-02",
        "tags": [
          "priority"
        ],
        "history": [
          57,
          62
        ],
        "delta": 5,
        "topIssue": null
      }
    ],
    "configuredEngines": [
      "ChatGPT",
      "Gemini"
    ],
    "portfolioHistory": [
      {
        "yearMonth": "2026-01",
        "avg": 57,
        "locations": 5
      },
      {
        "yearMonth": "2026-02",
        "avg": 62,
        "locations": 5
      }
    ],
    "systemicFixes": [
      {
        "factor": "citations",
        "label": "Citations",
        "detail": "6 locations are missing citations on Yelp.",
        "target": "citations",
        "count": 6,
        "pct": 30
      }
    ]
  }
}