GET /api/v1/sites
The sites in the workspace, by domain. Pass one as site to the tool endpoints.
curl https://aeoptimiz.com/api/v1/sites \ -H "Authorization: Bearer $AEOPTIMIZ_API_KEY"
AEOptimiz for developers
The same reads the assistant and the MCP server use, over plain HTTP: Search Console history, index coverage, opportunities and reviews. Read-only. Nothing here spends credits or changes anything.
Machine-readable: OpenAPI 3.1 document.
Create a key under Settings, then Developer. It is shown once. Send it with every request, either way:
Authorization: Bearer ikey_... x-api-key: ikey_...
A key reads the workspace it was created in, and stops working when it is revoked or when the person who created it leaves the workspace.
error message: 400 a body that is not a JSON object, 401 a missing or invalid key, 404 an endpoint that does not exist, 405 the wrong method, 413 a body too large, 422 a tool that could not answer.The sites in the workspace, by domain. Pass one as site to the tool endpoints.
curl https://aeoptimiz.com/api/v1/sites \ -H "Authorization: Bearer $AEOPTIMIZ_API_KEY"
The site's own context: locale, market, tech stack, positioning, tracked competitors, writing voice, and how much data has been mirrored. Call this first when you need to tailor an answer to the business rather than give generic SEO advice.
| Field | Type | About |
|---|---|---|
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/get_site_profile \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{}'The ranked list of what to fix, already scored by expected incremental monthly clicks. This is the engine's output: do NOT re-rank it, and do not invent findings that are not in it. Each row carries the evidence it was derived from, which is what you should quote. Where the site's GA4 property is joined, a row also carries `valuePerMonth`, already formatted with its currency: quote it exactly as given and never convert, scale or estimate it. Rows without one have no revenue data for that page, which is not the same as being worth nothing. A row carrying `availableAction` names a tool that fixes that kind of finding: offer it, and do not offer it for rows without one.
| Field | Type | About |
|---|---|---|
| detector | one of "striking", "cannibal", "decay", "ctr_gap", "demand_gap", "coverage" | Filter to one kind of finding. Omit for all. |
| limit | integer | Default 20. |
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/list_opportunities \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{}'Clicks, impressions and average position for one page over time, plus its top queries. Use it to check a claim before making it.
| Field | Type | About |
|---|---|---|
| url* | string | Full URL as it appears in Search Console. |
| days | integer | Default 90. |
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/get_page_performance \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{"url":"<url>"}'How the site performs for one search query, and which of its pages compete for it. Use it to confirm a cannibalisation finding before describing it.
| Field | Type | About |
|---|---|---|
| query* | string | |
| days | integer | Default 90. |
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/get_query_performance \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{"query":"<query>"}'Index coverage: how many submitted URLs Google has actually indexed, broken down by reason. This is the thing competing tools cannot answer, because a site: query returns a boolean with no coverage state, no crawl date and no Google-chosen canonical. Each class has a different fix.
| Field | Type | About |
|---|---|---|
| coverageClass | string | Drill into one class, e.g. not_discovered, discovered_not_crawled, crawled_not_indexed, duplicate_google_chose_other, excluded_noindex, soft_404, fetch_error. |
| limit | integer | Default 25. |
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/get_coverage \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{}'Whether this site ALREADY has a page about a topic. Call this BEFORE proposing any new page or article. It searches the site's own sitemap and every page that has earned an impression, and returns a verdict: duplicate (improve the existing page instead), related (write it, and link to the closest one), or clear. Proposing a page the customer published two years ago is the single most common complaint about tools in this category, and it happens because they cannot see the corpus.
| Field | Type | About |
|---|---|---|
| topic* | string | The proposed page title or target keyword, not a single word. |
| limit | integer | Default 5. |
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/check_existing_coverage \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{"topic":"<topic>"}'Compare one page against ITSELF, before and after a change was made. Use it whenever someone asks whether something they changed helped. Returns a verdict and both windows, and refuses to conclude anything when the data is too thin or too recent, which is the honest answer far more often than people expect.
| Field | Type | About |
|---|---|---|
| url* | string | Full URL as it appears in Search Console. |
| actionedAt* | string | The date the change was made, as YYYY-MM-DD. |
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/did_it_work \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{"url":"<url>","actionedAt":"<actionedAt>"}'How often AI assistants with web search cite this site, from the monthly probe: citation rate (the site's domain was among the sources the assistant's search retrieved), mention rate (the answer named the site), overall and per assistant (byAssistant: Claude, ChatGPT, Perplexity, Gemini, whichever were asked), both against the previous month, the hosts retrieved instead, and the questions where the site was not cited. Report citation and mention as two numbers, never as one score. Free: it reads stored results and runs nothing.
| Field | Type | About |
|---|---|---|
| site | string | The site to ask about, as its domain (for example example.com). Needed only when the workspace has more than one site; the first is used otherwise. |
curl https://aeoptimiz.com/api/v1/tools/get_ai_visibility \
-H "Authorization: Bearer $AEOPTIMIZ_API_KEY" \
-H "content-type: application/json" \
-d '{}'Prefer an AI app to a script? Connect it over MCP.
Questions about AEOptimiz?