ChatGPT Rank Tracking API — AI Visibility
Documentation menu
FetchLayer FetchLayer API

Track where a brand ranks in ChatGPT answers

Where a brand ranks among the options a ChatGPT answer recommends, over several answers to the same prompt — the AI analogue of a search rank check, and the route to use for tracking. Each run reports rank (null when the brand is not one of the recommendations), mentioned, citedAsSource, citationRank (its best position among the pages the answer cites, a separate ranking from the recommendations), method, the ordered recommendations the rank was read from, and competitorRanks. method says where the ranking came from, because answers are not laid out the same way twice: numbered_list, table, headings, bulleted_list, or first_mention when the answer presents no list at all and the ranking is the order your brands are first mentioned. A brand mentioned only in the surrounding prose has rank null and mentioned true. Answers vary between runs — the same prompt gives a different answer minutes apart — which is exactly why this route asks it repeatedly: read aggregate (mentionRate, averageRank, bestRank, worstRank, citationRate, averageCitationRank), not any single run, and keep prompt, country and webSearch fixed when comparing over time. runs is 1–5. Timing: every answer is a real ChatGPT session, and a request’s answers are generated alongside each other rather than one after the other — asking for more answers costs credits, not proportionally more time. Measured against the live service, the largest request this route accepts finishes inside a minute. For tracking wider than one request allows, run several smaller requests on a schedule and store the results, rather than trying to fit everything into one call. Billing: 1 credit per completed run; runs that could not be completed are noted and not billed.

POST /ai-rank AI visibility
https://api.fetchlayer.dev/chatgpt/ai-rank
OpenAPI JSON

Headers

Authorization string required

Bearer token — your FetchLayer API key.

Parameters

prompt string required

The prompt, exactly as a person would type it into ChatGPT (1–4000 characters).

target string | object required

The brand whose rank you want. A brand to look for: a name such as "FetchLayer", or an object { name, aliases[], domains[] }. Names and aliases match on whole words, case-insensitively — "Twenty" matches "twenty's" and "(TWENTY)", not "Twentyfold". Domains match when the answer writes them out, subdomains included and look-alikes excluded. Give aliases and domains when the name is an ordinary word.

competitors array optional

Brands to rank alongside it, up to 10. Same shape as target.

runs number optional

Separate answers to generate for the prompt, 1–5. Answers vary, so more runs give a steadier mentionRate and average rank. Each run is billed. (default: 1)

includeAnswers boolean optional

Include each run’s full answer. (default: false)

provider string optional

The assistant to ask. chatgpt is the only one available today; the field exists so the same request serves further assistants as they are added. (default: chatgpt)

country string optional

Two-letter country the answer should come from, such as US, GB or DE. Answers differ by country. When that country cannot be served, the answer comes from the default one and notes says so. (default: us)

language string optional

Language of ChatGPT’s own interface, such as en, de or pt-BR. The answer itself follows the language of your prompt. (default: en)

webSearch string optional

auto lets ChatGPT decide whether to search the web; on asks it to search before answering, and answer.usedWebSearch reports what it did. There is no "off": an anonymous visitor has no such setting. (default: auto)

format string optional

json or markdown. (default: json)

Response Fields

ai-rank

Track where a brand ranks in ChatGPT answers

resultType string

ask, mentions, ai-rank, prompt-discovery or visibility-report.

provider string

The assistant that was asked. Always "chatgpt" today.

requestedUrl string

The assistant page the answers correspond to.

transport string

The upstream source. Always "chatgpt".

notes string[]

Caveats you can act on — a country that could not be served, runs that could not be completed, details the answer did not show. Empty when there are none. Read it on every call.

answersGenerated number

Answers ChatGPT produced for this request.

pagesScraped number

Billable units, which is the same number: one credit per answer. An answer that could not be produced is never billed.

scrapedAt string

ISO 8601 timestamp of when the data was collected.

prompt string

The prompt that was asked, once per run.

target object

The brand as it was resolved: { name, aliases, domains }.

competitors object[]

The competitor brands, resolved the same way.

runsRequested number

Runs you asked for. Fewer may have completed — notes says so.

runs object[]

One entry per completed answer.

runs[].run number

1-based run number.

runs[].rank number

Position among the options this answer recommends, or null when the brand is not one of them.

runs[].mentioned boolean

Whether this answer names it anywhere, list or prose.

runs[].citedAsSource boolean

Whether this answer cites one of its pages.

runs[].citationRank number

Its best position among the cited sources, or null. Separate from rank.

runs[].method string

How this answer presented its options: numbered_list, table, headings, bulleted_list or first_mention. When an answer has several such structures, the one it presents first is used.

runs[].recommendations object[]

The ordered list the rank was read from, each { rank, name }.

runs[].competitorRanks object[]

Each competitor in this run: { name, rank, mentioned }.

runs[].usedWebSearch boolean

Whether this run used the web.

runs[].answeredAt string

When this run’s answer finished.

runs[].answer object

The full answer, when includeAnswers is true. null otherwise.

aggregate object

The figures over all completed runs. This is what tracking should read.

aggregate.runs number

Completed answers the figures are over.

aggregate.mentionRate number

Percentage of runs that mentioned the brand at all (0–100).

aggregate.averageRank number

Mean rank over the runs where it was ranked, or null when it never was. Runs where it was not ranked are left out rather than counted as last.

aggregate.bestRank number

Its best rank across the runs, or null.

aggregate.worstRank number

Its worst rank across the runs, or null.

aggregate.citationRate number

Percentage of runs whose answer cited one of its pages (0–100). This is a different measure from mentionRate: an answer can name a brand without citing it, and cite it without recommending it.

aggregate.averageCitationRank number

Mean position among the cited sources over the runs that cited it, or null.

competitorAggregates object[]

The same figures per competitor, each with its name.

Request

curl -X POST "https://api.fetchlayer.dev/chatgpt/ai-rank" \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"best reddit api alternatives","target":{"name":"FetchLayer","domains":["fetchlayer.dev"]},"competitors":["Apify"],"runs":2}'

Response

{
  "resultType": "ai-rank",
  "provider": "chatgpt",
  "requestedUrl": "https://chatgpt.com/",
  "transport": "chatgpt",
  "notes": [],
  "answersGenerated": 2,
  "pagesScraped": 2,
  "scrapedAt": "2026-09-16T02:22:36.665Z",
  "prompt": "best reddit api alternatives",
  "target": {
    "name": "FetchLayer",
    "aliases": [],
    "domains": [
      "fetchlayer.dev"
    ]
  },
  "competitors": [
    {
      "name": "Apify",
      "aliases": [],
      "domains": []
    }
  ],
  "runsRequested": 2,
  "runs": [
    {
      "run": 1,
      "rank": null,
      "mentioned": false,
      "citedAsSource": false,
      "citationRank": null,
      "method": "table",
      "recommendations": [
        {
          "rank": 1,
          "name": "Arctic Shift"
        },
        {
          "rank": 2,
          "name": "PullPush"
        },
        {
          "rank": 3,
          "name": "Managed Reddit REST APIs"
        },
        {
          "rank": 4,
          "name": "Apify Reddit scrapers"
        },
        {
          "rank": 5,
          "name": "Official Reddit API"
        }
      ],
      "competitorRanks": [
        {
          "name": "Apify",
          "rank": 4,
          "mentioned": true
        }
      ],
      "usedWebSearch": true,
      "answeredAt": "2026-09-16T02:22:36.614Z",
      "answer": null
    },
    {
      "run": 2,
      "rank": null,
      "mentioned": false,
      "citedAsSource": false,
      "citationRank": null,
      "method": "table",
      "recommendations": [
        {
          "rank": 1,
          "name": "Apify"
        },
        {
          "rank": 2,
          "name": "PRAW (Python Reddit API Wrapper)"
        },
        {
          "rank": 3,
          "name": "Pushshift Reddit Dataset"
        }
      ],
      "competitorRanks": [
        {
          "name": "Apify",
          "rank": 1,
          "mentioned": true
        }
      ],
      "usedWebSearch": true,
      "answeredAt": "2026-09-16T02:22:20.565Z",
      "answer": null
    }
  ],
  "aggregate": {
    "runs": 2,
    "mentionRate": 0,
    "averageRank": null,
    "bestRank": null,
    "worstRank": null,
    "citationRate": 0,
    "averageCitationRank": null
  },
  "competitorAggregates": [
    {
      "name": "Apify",
      "runs": 2,
      "mentionRate": 100,
      "averageRank": 2.5,
      "bestRank": 1,
      "worstRank": 4,
      "citationRate": 0,
      "averageCitationRank": null
    }
  ]
}