GET /v1/async/task/:id, or supply webhook.url when submitting; the task
reports taskType: "CITATION_ANALYSIS". Do not submit this analysis through
POST /v1/async/task; use the dedicated endpoint. Earlier names,
including GEO Audit’s, keep working: POST /v1/geo-audit,
POST /v1/source-influence and POST /v1/research, the GEO_AUDIT,
SOURCE_INFLUENCE and CITATION_ATTRIBUTION task types, and
include.geoAudit and include.sourceInfluence;
responses always use the new names.
Analyze a task you already ran
If the answer came from this API, send its task id. The analysis reads the answer and its citations from that task:COMPLETED, and still readable through
GET /v1/async/task/:id. Its answer Markdown (text when the engine returned no
Markdown) becomes answer, and its cited URLs become citations in the
engine’s order: the first 100, with at most 10 discussion threads. Product and
video card placeholders (googleusercontent.com links) and Google search links
are skipped, since they have no page to read. The task’s
prompt and country and its engine are used unless you send them. Sending
taskId together with answer or citations is rejected with 400, and so
is a task that is unfinished or has no answer text or cited URL. An unknown or
expired task id returns 404.
Analyze every answer as you collect it
Addinclude.citationAnalysis: true to a collection request, and the analysis
runs on the answer as soon as it is collected. It works with the answer engines
(CHATGPT, GEMINI, PERPLEXITY, GOOGLE_AIO, GOOGLE_AIMODE, NAVER_AI_BRIEF, NAVER_AI_TAB, BING_SEARCH, BING_COPILOT), in single tasks, task batches, grids and POST /v1/batches.
taskId does
above. The answer’s result then carries response.citationAnalysis: the
analysis task exactly as GET /v1/async/task/:id returns it, with task,
credits and response or error.
- Webhook: sent once, after the analysis finishes, with the answer and the analysis together.
- Polling: the answer task is
COMPLETEDas soon as the answer is ready. Keep polling untilresponse.citationAnalysis.task.statusisCOMPLETEDorFAILED. - Batches complete when every answer and its analysis have finished.
- No analysis: when the answer cites no URL to read, or your credits or the key’s daily limit cannot cover the analysis hold,
response.citationAnalysisis{ "error": "…" }and the answer is delivered right away. - Billing: the analysis is charged on its own, by usage like any Citation Analysis task. The answer’s charge does not change. A key limited to certain task types must also allow
CITATION_ANALYSIS.
Payload
With
taskId or include.citationAnalysis, these fields are filled from the
answer’s raw data. For CHATGPT, the engine’s searches become queries and every
page it retrieved becomes a citation with cited, position, citedText,
publishedAt and query; the same URL with different tracking parameters is
merged, and a page the answer links in its text or shows as a product card is
cited. For Google AI Overview, the overview’s sources are cited and organic
results outside them are non-cited, with position set to their organic rank.
Other engines provide cited sources only.
Result
Results stored before v4 keep their earlier shape, without aversion field.
version
Always 4 for this shape.
answer
The answer you submitted, unchanged. answerRanges are offsets into this exact
string: JavaScript UTF-16 code units, start inclusive, end exclusive. Slice
it as-is with answer.slice(start, end).
Each links[] range identifies a whole semantic unit of your answer: a sentence,
list item or table cell. Each brands[] range is the exact name as written.
Boundaries refer to the original text.
queries[]
The searches the engine ran for this answer. Each has an id, its text, and
sourceIds: the sources that search found. Empty when the engine exposed no
searches and you sent none.
sources[]: one entry per page
id: opaque identifier, unique within the result.url: the page URL;domain: its host.channel: who controls the page, judged from its host:own: your brand’s own site (exactly whenownistrue).brand: the own site of another brand the result names, judged by its domain or by the answer linking it from that brand’s name.editorial: a publisher; only the publisher can change the page. Hosts that are not recognized are reported aseditorial.retailer: an online store or marketplace.review_platform: a customer or business review site.community: a forum or Q&A site.video: a video platform.social: a social network.blog_platform: a hosted blog service.reference: an encyclopedia or wiki; never the target of an action.
cited:truewhen the answer cites the page,falsewhen the engine only retrieved it.position: the engine’s own rank for the page, ornullwhen it gave none.queryIds[]: the searches that found the page.publishedAt: the publication date as the engine reported it, ornull.citedText[]: passages the engine itself reported citing;[]when none.brandIds[]: brands named on the readable page, its title orcitedText.own:truewhen the page is on your brand’s own site.paragraphs[]: the paragraphs of a cited page included in the result. Each has anid(globally unique across the whole result) and thetextof the paragraph. A paragraph can be included with no link at all. Always empty for non-cited pages.error: present only when the page could not be read.paragraphsis then empty, and the string is a short reason for that source.
brands[]
Every brand the result tracks: your brand (role: "target"), your
competitors ("competitor"), and other brands the answer names ("answer").
rank: the order of the brand’s first name span in the answer, starting at 1;nullwhen the answer does not name the brand.answerRanges[]: the exact spans where the answer names the brand or one of its product names, in the same UTF-16 offsets, soanswer.slice(start, end)returns the name as written. Matching ignores case and takes whole words (except in scripts written without spaces); it covers headings and table cells, never link URLs or image markup.citedSourceIds[]: cited sources whose page names it.retrievedSourceIds[]: non-cited sources whose page names it.ownSourceIds[]: sources on the brand’s own site; filled for the target only.
links[]: one relationship per paragraph
paragraphId: the paragraph this link is about. It always points at a paragraph that exists insources[].answerRanges[]: the parts of the answer this paragraph corresponds to, asstart/endpairs in the same UTF-16 offsets as above. A link can carry several ranges; the same answer text is not repeated across them. Each range is a whole answer unit (sentence, list item or table cell).explanation: a short sentence describing the correspondence: what the paragraph states about that part of the answer.
visibility
Where your brand stands in this answer; null when no brand was sent.
brandId: your brand inbrands[].stage: one of:mentioned: the answer names your brand.on_cited_page: the answer does not name it, but a cited page does.on_retrieved_page: only pages the engine retrieved without citing name it.not_found: no page that was read names it.
rank: your brand’srankinbrands[].answerBrands: how many brands the answer names.
actions[]
Prioritized next steps for your brand; [] when no brand was sent. priority
starts at 1 (do first) and has no gaps. Actions are ordered by control: what
your brand controls first (owned), then platforms it can post on
(platform), then outreach (outreach). summary is one sentence and
steps[] holds one to five concrete steps, both in the answer’s language.
sourceIds, brandIds, queryIds and linkIds point at the evidence in this
result.
brandIds names your brand, or the rival brands those pages name. Third-party
pages that the engine retrieved without citing and that name your brand are
listed in brands[].retrievedSourceIds.
insights[]
Up to four short summaries of the result: which channels were cited, the
format, freshness or criteria the cited pages share, how the answer’s brand
order compares with what the cited pages cover, and where your brand sits.
sourceIds names the pages and linkIds the links each summary rests on; at
least one of them is non-empty, and they only name entries in this result.
The steps to take are in actions[].
Reading the result
- A paragraph without a link matched no part of this answer. An answer part with no range has no paragraph linked to it.
- Unread pages are left out. When
sources[].erroris set, run the analysis again or send the page’sbodyto include that citation. - Retrieval data depends on the engine. Non-cited pages appear only when the
engine exposes them (ChatGPT, Google AI Overview) or you send
cited: falsepages. Otherwise every source is cited, and your own page can only appear as cited. - Actions are ranked from the pages in this result. After you act on one, run the same prompt again and compare the answers.
- Ids are internal. Do not persist
s…/q…/b…/l…/a…identifiers as stable keys across runs; they are scoped to a single result.
Execution and limits
- Input size. The analysis takes an
answerup to 200,000 characters with up to 100 citations. Long answers, large source sets and very long pages are split into parts and analyzed. - Links follow the answer. The analysis links the passages that match each part of the answer, and every source with a match appears in the result. On a large page, or one that repeats the same statement in navigation, listings and reviews, it links the strongest passages.
- Links come from page text. Sitemaps, link indexes and image galleries add no links, and a page made only of those is reported with no paragraphs.
- A source that could not be read is reported in
sources[].errorwithout failing the task if another source is readable. The task fails when no source could be read, on an analysis failure, on a timeout, or on a service configuration error. - Requests are metered by usage, like the rest of the API. The submit response shows the temporary credit hold; the final charge is settled when the task reaches a terminal state.