Skip to main content
Compare a completed AI answer with its cited sources. The result says, for every sentence, list item, and table cell of the answer, which source supports it and with what content — and, just as important, which claims no source supports and which inline citations are decorative. This is post-hoc evidence analysis, not proof that a source caused the model to generate a sentence.
Poll GET /v1/async/task/:id, or supply webhook.url when submitting; the task reports taskType: "SOURCE_INFLUENCE". Do not submit this analysis through POST /v1/async/task; use the dedicated endpoint. POST /v1/research and the CITATION_ATTRIBUTION task type are the pre-September-2026 names and still work as deprecated aliases.

Payload

Result

claims[] — one per answer unit

The answer is split into sentences, list items, table cells, and headings. Each carries its exact range, the heading path it sits under (section), the brand or competitor names it mentions (entities, only when you passed them), the citation URLs linked inline at that claim, and every support entry linking it to a source’s evidence. status is computed from those links: support[].scope is full when the whole claim is supported and partial when only a substring is; a partial entry carries range, the supported substring in answer offsets (the claim’s own range stays the whole unit). support[].verbatim is true when the normalized claim and evidence contain each other — the strongest signal that the answer copied the source. Three fields come from a final reconcile pass that sees the whole verified ledger at once (never the source bodies) and can only annotate, never add support:
  • kind: specific_fact (a checkable fact a source could carry), derived (a number the answer computed from cited facts — a total, price × seats — not a gap), generic (common knowledge or framing), transition (structure, greeting, restated question). uncited × specific_fact is your content-opportunity list; summary.uncitedKinds counts them.
  • origin: for corroborated claims, the supporting source whose wording the claim follows most closely; null when indistinguishable.
  • support[].overclaim: a full support whose excerpt does not actually cover a number, condition or qualifier in the claim.
If that pass fails, debug.reconcile is failed; kind and origin remain null. Legacy overclaim: false is not a verified negative in this case. The rest of the result is unaffected.

sources[] — one per citation, same order

  • outcome: passage / post / comment when evidence was found, none when the source was read and nothing supports the answer, unfetched when the page could not be fetched (bot-challenge interstitials count as unfetched), error when analysing that source failed (the rest of the task still completes; error names the code), duplicate when the page repeats an earlier citation (duplicateOf gives its index; the page is judged once and never corroborates itself).
  • page: brandRelation (own, competitor, none, or null without a brand), publishedAt (discussion threads only), chars, and free-form tags describing what kind of page it is.
  • evidence[]: exact source excerpts. range addresses the supplied or fetched Markdown (for discussion threads, the post + comment snapshot). location says where on the page the content was: block (heading, paragraph, list_item, table_cell, blockquote, post, comment), headingPath, depth (0 = top of page, 1 = bottom), and permalink / score for comments. tags describe what kind of content it is; claims lists the answer claims it supports.
  • usage: influence (share of answer characters this source supports), rank (exclusive claims first, then verbatim matches, then influence), exclusiveClaims, and usedRatio (share of the page that was actually used — a low value on a cited page means most of it was ignored).

summary

coverage is the union of all supported answer ranges divided by answer length. ranking lists source indices, best first, for sources with influence above zero. claims counts each status. Filter claims[] by status for the gap list and sort sources[] by usage.usedRatio for under-used pages. Tags are free text on purpose: what kinds of content win is the question you are asking the data, so the taxonomy comes from your aggregate, not from a fixed enum.

Execution and limits

  • One full comparison per readable citation, all in parallel.
  • A single invalid match is dropped (debug.droppedMatches); a failed source is reported as error without failing the task. In legacy mode, the task fails when every source fails, on timeout, or on a configuration error. Opt-in mode preserves answer interpretation alongside source failures.
  • Repeated source fetches use caches. Unavailable pages remain unfetched.
  • Error codes: MISSING_CONFIG, ANALYSIS_FAILED, ANALYSIS_TIMEOUT.
  • debug.llmTokens and debug.sourceFetches feed the metered credit policy (1 + ⌈input tokens / 500⌉ + ⌈output tokens / 100⌉ + 2 per uncached fetch), capped by the submission hold (5 + 40 per citation + 6 per 1k answer characters).

Optional question and brand analysis

Set analysis.version to 1 on the same endpoint. The response remains version 2, with an additional analysis object. Omitting analysis preserves the existing result contract. The /v1/research alias accepts the same extension.
With the extension, citations accepts 0–25 entries. A missing question produces stages.requirements: "insufficient_context"; the answer is still analyzed. There is no separate answer-analysis API.

Trace a judgment to its evidence

analysis.requirements contains only the question’s explicit goals, mandatory conditions and preferences. Its evidence uses prompt offsets. A comparison criterion introduced by the answer is not a question requirement. analysis.decisions identifies a subject and a role: mention, recommendation, primary_recommendation, or against. evidence, subjectEvidence, conditions and reasons contain exact answer ranges. Conditional and conflicting judgments remain separate. List position does not establish a ranking. entityId: null means the subject could not be resolved. Unregistered entities have answer-derived identity and unknown ownership role; products retain their own ID and can reference a caller-provided brandId. Follow decision.claimIdsclaims[].supportsources[].evidence for the verified source relationship. analysis.summary.links is a convenience index of those same references. It labels each link supported, partial, overclaim, or unverified, and distinguishes judgment evidence from scope: "reason". A price-only passage does not establish the entire “best choice” conclusion. The summary counts unique judgment records, including neutral mention records; neutral facts for the same identified entity and identical conditions share one record, with separate evidence anchors and claim links. Facts already used as a recommendation reason are not counted again as neutral mentions. It does not assign causal contribution percentages. It gives no explanation for a brand’s absence.

Ownership and production are separate

Provide entity domains as hostnames, without schemes or paths. Matching uses hostname boundaries: docs.atlas.example matches atlas.example, while notatlas.example and atlas.example.evil.test do not. Unknown sites remain unknown; a third-party domain is not automatically independent or earned. Entity names and aliases must unambiguously identify one entity. A citation can independently carry:
our-brand must be an input entity ID. Ownership is own, competitor, third_party or unknown; production is direct, commissioned, independent or unknown. Explicit page metadata takes precedence over domain matching and is labeled caller; domain matching is labeled caller_domain. Neither is represented as independently verified. Page content types remain in existing page.tags and evidence tags. Legacy page.brandRelation keeps its old heuristic meaning; consumers of this extension should use analysis.sourceRelationships.

Completion, original texts and cost

Check analysis.status and analysis.stages, even when the task is COMPLETED. A failed interpretation is not an empty successful recommendation list. Source failures, no source targets, insufficient question context and incomplete reconciliation are separate states. Valid source results survive interpretation failure. Independently validated question requirements also survive a failed decision section. Decisions can survive failed requirements only when they do not reference those requirements. Such results are partial; failed sections remain empty. Links are unverified when reconciliation cannot certify them. All ranges are exact UTF-16 offsets. analysis.documents hashes the actual answer, question and source representation using SHA-256 over UTF-16LE bytes; it also identifies caller bodies separately. A supplied body, including an empty snapshot, is never silently replaced by a current page. fetchedAt is null when unknown, and historicalMatch remains unknown: a current fetch does not recreate the page at the answer’s historical time. Optional analysis.answeredAt records that answer time. analysisKey includes original data, entity/relationship inputs, source identities, model configuration and analysis version. It is an identity for downstream reanalysis, not a server-side analysis cache or an idempotency key. The extension uses higher reasoning effort than the legacy default, with higher token use and latency. Costs vary with input. The extension shares the final reconcile call and the existing concurrency, cancellation and timeout controls. An invalid structured result may receive one corrective model call within the same budget and deadline. Source calls are not repeated. The HIGH/max output cap is 32,768 tokens, including reasoning. Oversized interpretation fails explicitly with ANALYSIS_INPUT_TOO_LARGE; text is not silently truncated. The temporary credit hold adds a payload-sized input/output budget. The runtime enforces that same budget across source windows and final interpretation. Calls wait for in-flight usage to settle; exhausted budgets fail explicitly before another model call. URL-only citations reserve a 16k-character window estimate; supplied bodies use their actual length. Longer fetched pages can exhaust the allocation and produce explicit partial/failure states. Existing token and source-fetch prices are unchanged; only actual metered usage is charged. debug.modelCalls counts all attempted model calls in opt-in mode; debug.judgeCalls still counts source-window calls. llmTokens includes reconciliation and known failed-call usage. Unknown provider usage after an interrupted call cannot be reconstructed. uncited means no support was found in the inspected source set. Unread sources leave uncertainty; this is neither a claim about the whole web nor a prediction that new content will succeed. Existing influence, publisher exclusivity and wording-origin metrics do not measure causal generation effects.