Get latest AI sources data
Changed onGet the latest AI Sources data for a project: for each engine we ask — Perplexity and Google AI Overviews — which companies it named in answer to the project's 8 buying questions, which pages it RETRIEVED to answer, and which of the pages more than one engine retrieved name other companies and not the customer. Every number is read off the stored summary of the latest published check, the same document the app shows. Two sentences this data cannot support, and no field here claims: a CITATION count — an engine hands back the pages it retrieved while answering and does not say which it leaned on — and a POOLED page number — the engines read different pages, so page counts are per engine and are never added together. The one cross-engine object is the core, the hosts at least 2 engines retrieved (summary.overlap, summary.coreHosts); answers may pool as a vote on the leaderboard (summary.brands), and every such row says which engines back it. Counts are counts, never rates: report figures as n of N answers and never as a percentage or a share — the question set is small by design, and a share computed from it is false precision. Every count names its universe on the same object. An engine the check did not ask is ABSENT from every per-engine record, and absent means not measured, never zero; an engine present with engineDataAvailable produced nothing usable and carries no count. The question matrix has three cell states, never two: answered, no_answer_shown (the engine was read and showed nothing — measured, not an answer, not a failure) and not_measured (we could not read it — not a zero). A page we could not read is listed under its host with its reason and is never counted as a page the customer is absent from; only a core host whose status is missing supports 'get onto this page'. actionHint.text on each core host and the sentences under summary.limits.sentences are payload: render them verbatim. Set includeAnswers=true to also get the engines' raw answers on that check — the answer text, the companies read out of it in order of first mention, and the pages each engine retrieved with the passage it handed back — narrowed by engine= or promptIndex=. The block is large; the prose in it is the engine's, not CompetLab's. No filter changes a number under summary. When the most recent check was abandoned because no engine produced a usable answer, latestCheckDataAvailable is present and everything else describes an earlier check. A project with no published check yet answers 404 no_data_available — not a missing project and not a failed measurement, just nothing measured here so far; the project itself is fine and get_project still describes it. Distinguish it from project_not_found, which means the id is wrong.
Request
- Base URL: https://api.competlab.com
- URL: https://api.competlab.com/v1/projects/{projectId}/ai-sources
- Auth: API key in header CL-API-Key
Path parameters
Project ID
Query parameters
Set true to include what the engines actually said — every question sent, the answer text, the companies read out of it in order of first mention, and the pages the engine RETRIEVED to write it, with the passage it handed back for each. Off by default because the block is large: up to 8 answers per engine, each carrying the engine's full retrieved page list, which for a searching engine can run to dozens of pages with a passage each. Narrow with engine= or promptIndex= rather than fetching everything. The answer text is the engine's wording, not CompetLab's assessment; the pages are retrieved, never cited.
The OTHER engines that also retrieved this host this check. Empty means only this engine did. Membership, never a count.
Return only this engine's answers. Requires includeAnswers=true. Narrows answers, unansweredQueries and noAnswerShown; changes nothing under summary and does not narrow engineStatus.
Return only the answers for this question, across every engine. Requires includeAnswers=true. Zero-based: the question's position in the check's question list, matching promptIndex on each answer.
How much of the response to return. compact: summary.pages and summary.brands are one page of rows each, with summary.pagesPage and summary.brandsPage saying where it sits (the customer's own brand row is always included); each summary.coreHosts[] lists its pages as pageUrls, every one a row of summary.pages reachable with pagesHost. Every other field is unchanged. full: every row of every list, as stored — large, and meant for export rather than for reading. Omitted, the API's default view applies: compact on /v1.
Return only the rows of summary.pages on this host, matched exactly and case-insensitively; a leading www. is ignored on both sides, so www.g2.com and g2.com are the same host. Use a summary.coreHosts[].host to read that host's pages. summary.pagesPage.total counts the rows after this filter. Pages the compact view: sent without view it selects the compact view, and beside view=full it is refused with paging_requires_compact_view.
Rows of summary.pages to skip, in the order the list is stored. Default 0. Pages the compact view: sent without view it selects the compact view, and beside view=full it is refused with paging_requires_compact_view.
Rows of summary.pages to return, 1 to 100. Default 10. Pages the compact view: sent without view it selects the compact view, and beside view=full it is refused with paging_requires_compact_view.
Rows of summary.brands to skip, in the order the list is stored. Default 0. Pages the compact view: sent without view it selects the compact view, and beside view=full it is refused with paging_requires_compact_view.
Rows of summary.brands to return, 1 to 200. Default 10. Pages the compact view: sent without view it selects the compact view, and beside view=full it is refused with paging_requires_compact_view.
Response
Example response
{
"item": {
"readingGuide": {
"summary.pages": "Pages the engines RETRIEVED while answering, never pages they cited."
},
"lastUpdatedAt": "2026-09-04T10:00:00.000Z",
"summary": {
"customerDomain": "mycompany.com",
"window": {
"checkIds": [
"507f1f77bcf86cd799439012",
"507f1f77bcf86cd799439011"
],
"since": "2026-08-01T10:00:00.000Z",
"perEngine": {
"perplexity": {
"checkIds": [
"507f1f77bcf86cd799439012"
]
},
"google_ai_overviews": {
"checkIds": [
"507f1f77bcf86cd799439012"
]
}
}
},
"perEngine": {
"perplexity": {
"engineDataAvailable": {
"reason": "no_usable_answer"
},
"answersAsked": 8,
"answersReceived": 7,
"answersAbsent": 1,
"answersWithoutRetrieval": 1,
"answersNamingCustomer": 3,
"answersRetrievingOwnPage": 4,
"pagesRetrieved": 131,
"hostsRetrieved": 58,
"hostsOnlyThisEngine": 33,
"engineCoreSize": 35,
"pagesRead": 118,
"pagesUnreadable": 9,
"pagesNotFetched": 4,
"ownPagesRetrieved": 6,
"independentPagesNamingCustomer": {
"floor": 4,
"ceiling": 6
},
"topHosts": [
{
"host": "g2.com",
"pages": 3,
"alsoRetrievedBy": [
"google_ai_overviews"
]
}
]
},
"google_ai_overviews": {
"engineDataAvailable": {
"reason": "no_usable_answer"
},
"answersAsked": 8,
"answersReceived": 7,
"answersAbsent": 1,
"answersWithoutRetrieval": 1,
"answersNamingCustomer": 3,
"answersRetrievingOwnPage": 4,
"pagesRetrieved": 131,
"hostsRetrieved": 58,
"hostsOnlyThisEngine": 33,
"engineCoreSize": 35,
"pagesRead": 118,
"pagesUnreadable": 9,
"pagesNotFetched": 4,
"ownPagesRetrieved": 6,
"independentPagesNamingCustomer": {
"floor": 4,
"ceiling": 6
},
"topHosts": [
{
"host": "g2.com",
"pages": 3,
"alsoRetrievedBy": [
"google_ai_overviews"
]
}
]
}
},
"matrix": [
{
"promptId": "7f3c1a2e-9d44-4c8b-9f0e-2b6a5c9d7e10",
"promptText": "Which email warm-up tools are safe to use with a Google Workspace domain?",
"cells": {
"perplexity": {
"companiesNamed": 6,
"webSearch": {
"performed": true,
"completedSearchCount": 3,
"reason": "NO_SEARCH_ATTEMPTED"
},
"pagesRetrieved": 14,
"pagesRead": 12,
"pagesUnreadable": 1,
"pagesNotFetched": 1,
"pagesNamingCustomer": {
"floor": 4,
"ceiling": 6
},
"ownPagesRetrieved": 1
},
"google_ai_overviews": {
"companiesNamed": 6,
"webSearch": {
"performed": true,
"completedSearchCount": 3,
"reason": "NO_SEARCH_ATTEMPTED"
},
"pagesRetrieved": 14,
"pagesRead": 12,
"pagesUnreadable": 1,
"pagesNotFetched": 1,
"pagesNamingCustomer": {
"floor": 4,
"ceiling": 6
},
"ownPagesRetrieved": 1
}
}
}
],
"brands": [
{
"domain": "competitor.com",
"name": "Competitor Inc",
"rankByPresence": 2,
"answers": {
"answersNaming": 5,
"answersReceived": 16,
"presence": 31,
"presenceLow": 14,
"presenceHigh": 56
},
"answersRetrievingOwnSite": {
"answersNaming": 5,
"answersReceived": 16,
"presence": 31,
"presenceLow": 14,
"presenceHigh": 56
},
"enginesNaming": [
"perplexity"
],
"perEngine": {
"perplexity": {
"answers": {
"answersNaming": 5,
"answersReceived": 16,
"presence": 31,
"presenceLow": 14,
"presenceHigh": 56
},
"independentPagesNaming": {
"floor": 4,
"ceiling": 6
},
"pagesRead": 118,
"ownPagesRetrieved": 2
},
"google_ai_overviews": {
"answers": {
"answersNaming": 5,
"answersReceived": 16,
"presence": 31,
"presenceLow": 14,
"presenceHigh": 56
},
"independentPagesNaming": {
"floor": 4,
"ceiling": 6
},
"pagesRead": 118,
"ownPagesRetrieved": 2
}
}
}
],
"brandsPage": {
"limit": 10,
"total": 96,
"hasMore": true
},
"overlap": {
"hostsInCore": 25,
"perEngine": {
"perplexity": {
"hostsRetrieved": 58,
"hostsOnlyThisEngine": 33
},
"google_ai_overviews": {
"hostsRetrieved": 58,
"hostsOnlyThisEngine": 33
}
}
},
"funnel": {
"coreHosts": 25,
"alreadyNamingCustomer": 19,
"unreadable": 2,
"missing": 4,
"missingPublishers": 3,
"missingCompetitorOwned": 1
},
"coreHosts": [
{
"host": "g2.com",
"ownedBy": "competitor.com",
"kindCheckedAt": "2026-09-04",
"actionHint": {
"code": "sources_retrieved_not_cited",
"text": "Retrieved, never cited: these are the pages the engine pulled back while answering; which of them it leaned on is not something the engines disclose."
},
"engines": [
"perplexity",
"google_ai_overviews"
],
"seenInChecks": {
"perplexity": {
"checkIds": [
"507f1f77bcf86cd799439012"
]
},
"google_ai_overviews": {
"checkIds": [
"507f1f77bcf86cd799439012"
]
}
},
"brandsNamed": [
"competitor.com"
],
"pages": [
{
"key": "g2.com/categories/email-warm-up",
"url": "https://www.g2.com/categories/email-warm-up",
"host": "g2.com",
"title": "Best Email Warm-Up Software",
"engines": [
"perplexity",
"google_ai_overviews"
],
"ownedBy": "competitor.com",
"fetchedAt": "2026-09-04T10:00:00.000Z",
"brandsNamed": [
"competitor.com",
"rival.io"
],
"excerpt": "…the most reliable options this year are Competitor Inc and Rival…"
}
],
"pageUrls": [
"https://www.g2.com/categories/email-warm-up"
]
}
],
"ownPageRetrievals": [
{
"promptId": "7f3c1a2e-9d44-4c8b-9f0e-2b6a5c9d7e10",
"pages": [
{
"key": "mycompany.com/pricing",
"url": "https://mycompany.com/pricing",
"title": "Pricing — My Company"
}
],
"companiesNamed": [
"competitor.com",
"rival.io"
]
}
],
"pages": [
{
"key": "g2.com/categories/email-warm-up",
"url": "https://www.g2.com/categories/email-warm-up",
"host": "g2.com",
"title": "Best Email Warm-Up Software",
"engines": [
"perplexity",
"google_ai_overviews"
],
"ownedBy": "competitor.com",
"fetchedAt": "2026-09-04T10:00:00.000Z",
"brandsNamed": [
"competitor.com",
"rival.io"
],
"excerpt": "…the most reliable options this year are Competitor Inc and Rival…"
}
],
"pagesPage": {
"limit": 10,
"total": 96,
"hasMore": true,
"host": "g2.com"
},
"limits": {
"pagesRetrieved": 153,
"pagesRead": 140,
"pagesUnreadable": 9,
"pagesNotFetched": 4,
"pagesTruncated": 3,
"unreadableByReason": {
"bot_protection": 5,
"host_blocked_recently": 2,
"text_too_short": 1,
"timeout": 1
},
"textSourceMix": {
"body": 140,
"snippet_only": 9,
"none": 4
},
"sentences": [
{
"code": "sources_retrieved_not_cited",
"text": "Retrieved, never cited: these are the pages the engine pulled back while answering; which of them it leaned on is not something the engines disclose."
}
]
}
},
"trackedDomains": [
"mycompany.com",
"competitor.com"
],
"latestCheckDataAvailable": {
"reason": "no_usable_answer_from_any_engine",
"enginesAsked": [
"perplexity",
"google_ai_overviews"
]
},
"answers": [
{
"promptId": "7f3c1a2e-9d44-4c8b-9f0e-2b6a5c9d7e10",
"promptText": "Which email warm-up tools are safe to use with a Google Workspace domain?",
"askedIn": {
"locationName": "United States",
"languageName": "English"
},
"answerText": "For a Google Workspace domain, the safest warm-up tools are Competitor Inc and Rival, both of which…",
"companiesNamed": [
{
"rank": 1,
"name": "Competitor Inc",
"domain": "competitor.com"
}
],
"sources": [
{
"url": "https://www.g2.com/categories/email-warm-up",
"domain": "g2.com",
"title": "Best Email Warm-Up Software",
"snippet": "Warm-up tools gradually increase sending volume so that mailbox providers…",
"publishedAt": "2026-05-12",
"resolvedFrom": "https://www.google.com/goto?url=…"
}
],
"searchQueries": [
"email warm-up tools Google Workspace safe"
],
"webSearch": {
"performed": true,
"completedSearchCount": 3,
"reason": "NO_SEARCH_ATTEMPTED"
}
}
],
"unansweredQueries": [
{
"promptIndex": 5,
"promptId": "7f3c1a2e-9d44-4c8b-9f0e-2b6a5c9d7e10",
"promptText": "Which email warm-up tools have a free plan?",
"reason": "no_usable_answer"
}
],
"noAnswerShown": [
{
"promptIndex": 3,
"promptId": "7f3c1a2e-9d44-4c8b-9f0e-2b6a5c9d7e10",
"promptText": "Which email warm-up tools have a free plan?",
"reason": "no_ai_overview_shown"
}
],
"engineStatus": {
"perplexity": {
"reported": true,
"completedAt": "2026-09-04T10:00:00.000Z",
"questionsAsked": 8,
"answersReceived": 7,
"answersAbsent": 1
},
"google_ai_overviews": {
"reported": true,
"completedAt": "2026-09-04T10:00:00.000Z",
"questionsAsked": 8,
"answersReceived": 7,
"answersAbsent": 1
}
}
}
}Changes
- breaking
the response property
////////became nullable for the status - breaking
the response property
////////became optional for the status - warning
added the new
nothing_to_returnenum value to the/response property for the response status - warning
added the new
paging_requires_compact_viewenum value to the/response property for the response status - warning
added the new
paging_requires_summaryenum value to the/response property for the response status - info
added the new optional
queryrequest parameterbrandsLimit - info
added the new optional
queryrequest parameterbrandsOffset - info
added the new optional
queryrequest parameterpagesHost - info
added the new optional
queryrequest parameterpagesLimit - info
added the new optional
queryrequest parameterpagesOffset - info
added the new optional
queryrequest parameterview - info
added the optional property
/to the response with the status - info
added the optional property
//////to the response with the status - info
added the optional property
////////to the response with the status - info
added the optional property
//////to the response with the status
- breaking
- warning
added the new
bad_requestenum value to the/response property for the response status - warning
added the new
not_foundenum value to the/response property for the response status
- warning