MyAEO API · v1

API documentation

Run scans, read results, and pull PDF reports from your own scripts and integrations. POST endpoints, JSON in / JSON out, authenticated with a single API key.

What you can do

  • Kick off a new scan against your active brand.
  • List every scan you've ever run, or fetch just the latest one with its current status.
  • Pull the full results of a scan: per-prompt model responses, mention & citation flags, and aggregate rates.
  • Generate a PDF report for any scan — the same data that powers the dashboard's Print Report.
  • List every blog post you've rewritten in MyAEO and fetch its markdown body.

Conventions

  • Base URL: https://myaeo.app/api/v1
  • Method: all endpoints are POST.
  • Body: JSON (Content-Type: application/json).
  • Auth: bearer token in the Authorization header.
  • Errors: JSON in the shape { error: string } with a non-2xx status code.

Generating an API key

Each MyAEO account has one active API key. Generating a new key replaces the old one — anything still using the previous key will stop working.

  1. Sign in to MyAEO and open Settings → API.
  2. Click Generate API key.
  3. Copy the key with the Copy button. It looks like:
API key format
myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// "myaeo_key_" prefix + 35 random alphanumeric characters

Treat the key like a password. Anyone holding it can read your scans and rewritten posts. If it leaks or you want to rotate it, click Generate new key on the same screen.

Open Settings → API

Authentication

Send the API key on every request as a bearer token in the Authorization header.

HTTP headers
Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Requests with a missing, malformed, or revoked key get a 401 response.

start-scan

POST/api/v1/start-scan

Kicks off a new scan against your active brand using all approved prompts and all enabled models. Web search is enabled. Returns immediately with the new scan ID — poll get-latest-scan or get-scan-results to follow progress.

Request body

No body required. Send {} or omit the body.

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/start-scan' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{}'
JavaScript
const res = await fetch("https://myaeo.app/api/v1/start-scan", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const data = await res.json();
console.log(data);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/start-scan",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={},
)
print(res.json())

Example response

JSON
{
  "scan_id": "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e",
  "status": "running",
  "started_at": "2026-04-25T18:32:11.482Z",
  "total_responses": 12
}

get-scans

POST/api/v1/get-scans

Returns every scan you've ever run, newest first.

Request body

No body required. Send {} or omit the body.

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/get-scans' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{}'
JavaScript
const res = await fetch("https://myaeo.app/api/v1/get-scans", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const data = await res.json();
console.log(data);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/get-scans",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={},
)
print(res.json())

Example response

JSON
{
  "scans": [
    {
      "scan_id": "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e",
      "scanned_at": "2026-04-25T18:32:11.482Z",
      "time_ago": "12h ago"
    },
    {
      "scan_id": "1f9b22c5-3a8e-4dde-b5e7-7e1a2b3c4d5e",
      "scanned_at": "2026-04-22T09:14:00.000Z",
      "time_ago": "4d ago"
    }
  ]
}

get-latest-scan

POST/api/v1/get-latest-scan

Returns the most recent scan you've run, regardless of status. Same shape as get-scan-results, but skips the scan-id lookup. The status field tells you whether the scan is still running, has completed, or failed.

Request body

No body required. Send {} or omit the body.

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/get-latest-scan' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{}'
JavaScript
const res = await fetch("https://myaeo.app/api/v1/get-latest-scan", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const data = await res.json();
console.log(data);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/get-latest-scan",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={},
)
print(res.json())

Example response

JSON
{
  "scan_id": "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e",
  "status": "running",
  "started_at": "2026-04-25T18:32:11.482Z",
  "finished_at": null,
  "summary": {
    "mention_amount": 4,
    "cited_amount": 1,
    "mention_rate": 67,
    "cited_rate": 17,
    "total_responses": 6
  },
  "prompts": [
    {
      "prompt_id": "5d8e1a2b-…",
      "prompt": "Best CRM for small startups in 2026",
      "category": "Comparison",
      "models": [
        {
          "model": "openai/gpt-5.4",
          "model_label": "ChatGPT",
          "status": "completed",
          "response": "For small startups in 2026, popular options include …",
          "mentioned": true,
          "cited": false,
          "cited_urls": [],
          "error": null
        }
      ]
    }
  ]
}

get-scan-results

POST/api/v1/get-scan-results

Returns the full results of one scan: per-prompt model responses, mention/citation flags, and aggregate rates.

Request body

JSON
{
  "scan_id": "<scan id from get-scans>"
}

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/get-scan-results' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "scan_id": "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e" }'
JavaScript
const res = await fetch("https://myaeo.app/api/v1/get-scan-results", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ scan_id: "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e" }),
});
const data = await res.json();
console.log(data);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/get-scan-results",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={"scan_id": "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e"},
)
print(res.json())

Example response

JSON
{
  "scan_id": "8c3f12e4-9a2b-4c8a-9c6e-1d2b3a4c5d6e",
  "status": "completed",
  "started_at": "2026-04-25T18:32:11.482Z",
  "finished_at": "2026-04-25T18:34:48.701Z",
  "summary": {
    "mention_amount": 9,
    "cited_amount": 4,
    "mention_rate": 75,
    "cited_rate": 33,
    "total_responses": 12
  },
  "prompts": [
    {
      "prompt_id": "5d8e1a2b-…",
      "prompt": "Best CRM for small startups in 2026",
      "category": "Comparison",
      "models": [
        {
          "model": "openai/gpt-5.4",
          "model_label": "ChatGPT",
          "status": "completed",
          "response": "For small startups in 2026, popular options include …",
          "mentioned": true,
          "cited": false,
          "cited_urls": [],
          "error": null
        },
        {
          "model": "perplexity/sonar-pro-search",
          "model_label": "Perplexity",
          "status": "completed",
          "response": "Several CRMs stand out for startups…",
          "mentioned": true,
          "cited": true,
          "cited_urls": ["https://yourbrand.com/crm-guide"],
          "error": null
        }
      ]
    }
  ]
}

generate-report

POST/api/v1/generate-report

Generates a PDF report of a scan — same data that powers the dashboard's Print Report. Pass a scan_id to target a specific scan, or omit it to use the latest completed scan. Unlike the other endpoints, this one returns the PDF bytes directly with Content-Type: application/pdf — not JSON.

Request body

JSON (optional)
{
  "scan_id": "<scan id from get-scans>"  // optional — omit to use latest completed scan
}

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/generate-report' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{}' \
  --output report.pdf
JavaScript
const res = await fetch("https://myaeo.app/api/v1/generate-report", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const blob = await res.blob();
// In Node: const buf = Buffer.from(await res.arrayBuffer());
//          fs.writeFileSync("report.pdf", buf);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/generate-report",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={},
)
with open("report.pdf", "wb") as f:
    f.write(res.content)

Response

On success: 200 with a PDF body. The Content-Disposition header sets a default filename like MyAEO Report - 2026-04-26.pdf.

On failure: standard JSON error shape { error: string } with a non-2xx status.

get-posts

POST/api/v1/get-posts

Returns every post you've rewritten in MyAEO, newest first.

Request body

No body required. Send {} or omit the body.

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/get-posts' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{}'
JavaScript
const res = await fetch("https://myaeo.app/api/v1/get-posts", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const data = await res.json();
console.log(data);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/get-posts",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={},
)
print(res.json())

Example response

JSON
{
  "posts": [
    {
      "post_id": "a1b2c3d4-…",
      "headline": "How modern CRMs are rebuilding for AI-first workflows",
      "status": "completed",
      "written_at": "2026-04-25T19:02:44.103Z"
    },
    {
      "post_id": "f5e6d7c8-…",
      "headline": "The 7 sales-automation patterns that actually move revenue",
      "status": "completed",
      "written_at": "2026-04-23T10:11:00.000Z"
    }
  ]
}

get-post-content

POST/api/v1/get-post-content

Returns the full markdown body of a single post.

Request body

JSON
{
  "post_id": "<post id from get-posts>"
}

Example request

cURL
curl -X POST 'https://myaeo.app/api/v1/get-post-content' \
  -H 'Authorization: Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "post_id": "a1b2c3d4-..." }'
JavaScript
const res = await fetch("https://myaeo.app/api/v1/get-post-content", {
  method: "POST",
  headers: {
    "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ post_id: "a1b2c3d4-..." }),
});
const data = await res.json();
console.log(data);
Python
import requests

res = requests.post(
    "https://myaeo.app/api/v1/get-post-content",
    headers={
        "Authorization": "Bearer myaeo_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "Content-Type": "application/json",
    },
    json={"post_id": "a1b2c3d4-..."},
)
print(res.json())

Example response

JSON
{
  "post_id": "a1b2c3d4-…",
  "headline": "How modern CRMs are rebuilding for AI-first workflows",
  "status": "completed",
  "written_at": "2026-04-25T19:02:44.103Z",
  "markdown": "# How modern CRMs are rebuilding for AI-first workflows\n\nIn 2026, the way teams sell has fundamentally shifted…"
}

Errors

All errors return a non-2xx status code and a JSON body shaped { error: string }.

StatusMeaning
400Body wasn't valid JSON, or a required field is missing.
401API key is missing, malformed, or revoked.
402Out of credits — top up in Settings → Account.start-scan only.
404Resource doesn't exist or isn't owned by this key.
500Unexpected error — try again or contact support.
502Couldn't reach the scan worker — try again in a moment. start-scan only.

Need help? Join the Telegram group chat.