Get how the market the AI models draw has moved
Changed onHow the market the AI models draw has moved over a window: one row per company with how often it was recommended at the start of the window and now — a share of the answers pooled in each check's window, with a 95% range and a zone — plus its rank by that share and its AI Visibility Score at both ends, the difference between the ends in each unit, and the models backing it. The project's own company and every tracked competitor are always rows, however many there are, plus up to 3 companies the project does not track (the most recommended of the rest with a reading on the scope), all ordered by how often each is recommended on the latest map (ties are ties, so never break one). Each reading carries checksAnalysed, the checks its map pools: now is never the latest check alone. Two companies whose ranges overlap are not in a settled order whatever their shares say. The score counts only the top 5 positions in an answer, evenly spaced — first place the most, the last scoring position the least — and nothing below them. It is a reading of WHERE a brand lands when it is named, never of who is ahead: a standing claim — "you lead", "you trail", "the leader is X" — rests on how often each brand is named (presence on the market map, or mentionRate within one check) and never on this score, which can favour a brand named half as often. A score of 0 for a brand the answers did name means it was named only below the top 5, or too seldom inside them for the average to register. events carries what happened on the axis: the customer's own standing changing zone and holding (the alerts the customer received — a standing is announced only once it has held for two checks), the cycles that produced no reading, and when the prompts were last edited (readings before that date answer different questions). provider reads one model's own slice of every map; rank and score are then absent, since they exist only across every model. detail=series adds each company's share check by check, downsampled to at most twelve points; omit it unless the shape between the ends matters. The window reads at most the newest 200 published checks — use dateFrom/dateTo for longer histories. Every figure here is a stored map's own: a company a map does not carry is a measured zero of that map's answers, and a model with no usable answer in a window is null, never zero.
Request
- Base URL: https://api.competlab.com
- URL: https://api.competlab.com/v1/projects/{projectId}/ai-visibility/trend
- Auth: API key in header CL-API-Key
Path parameters
Project ID
Query parameters
Start of the window (ISO-8601). Omit for the whole history: the newest 200 published checks, and the newest 200 cycles that produced no reading — on a longer history set both dates so the two cover one span.
End of the window (ISO-8601).
Read one AI model's own slice of every map instead of the pooled map. Omit for every model at once. Under one model rank and score are null on every reading and enginesBacking is left off the rows — they exist only across every model; never read that as 'no model named them'.
series adds each company's share check by check, downsampled to at most 12 points spread evenly over the window. Omit it unless the shape between the two ends matters: the rows already carry the reading now, the reading at the start and the difference.
Response
Example response
{
"item": {
"window": {
"from": "2026-08-12T09:30:00.000Z",
"to": "2026-08-30T09:30:00.000Z",
"checks": 16,
"answersReceived": 60,
"checksAnalysed": 5,
"providersAsked": [
"openai",
"claude",
"gemini",
"perplexity",
"google_ai_overviews"
]
},
"companies": [
{
"name": "Acme",
"domain": "acme.com",
"isTracked": true,
"enginesBacking": [
"openai",
"claude"
],
"now": {
"date": "2026-08-30T09:30:00.000Z",
"checkId": "507f1f77bcf86cd799439012",
"checksAnalysed": 5,
"presence": {
"answersNaming": 24,
"answersReceived": 60,
"presence": 40,
"presenceLow": 28,
"presenceHigh": 53
},
"rank": 3,
"score": 41
},
"start": {
"date": "2026-08-30T09:30:00.000Z",
"checkId": "507f1f77bcf86cd799439012",
"checksAnalysed": 5,
"presence": {
"answersNaming": 24,
"answersReceived": 60,
"presence": 40,
"presenceLow": 28,
"presenceHigh": 53
},
"rank": 3,
"score": 41
},
"presenceChange": 12,
"presenceChangeSeparable": true,
"rankChange": 2,
"scoreChange": 9,
"series": [
{
"date": "2026-08-20T09:30:00.000Z",
"checksAnalysed": 5,
"presence": 27,
"presenceLow": 17,
"presenceHigh": 40
}
]
}
],
"events": {
"standingChanges": [
{
"date": "2026-08-26T09:30:00.000Z"
}
],
"incompleteCycles": [
{
"date": "2026-03-14T02:00:00.000Z",
"reason": "incomplete_coverage",
"measuredAnswers": 8,
"expectedAnswers": 12,
"absentAnswers": 1
}
],
"promptsLastChangedAt": "2026-08-16T14:00:00.000Z"
}
}
}Changes
- info
added the required property
////////to the response with the status - info
added the required property
/////to the response with the status - info
added the required property
////////to the response with the status
- info
- breaking
removed the required property
from the response with the status - breaking
removed the required property
from the response with the status - info
added the new optional
queryrequest parameterdetail - info
added the new enum value
google_ai_overviewsto thequeryrequest parameterprovider - info
added the new enum value
perplexityto thequeryrequest parameterprovider - info
added the required property
to the response with the status
- breaking