Skip to content

Competitor performance

Deep analysis of how you compare to competitors in AI responses.

Code example

Request
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&days=30&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "brand_performance_summary": [
    { "brand_name": "Notion", "total_mentions": 127, "avg_rank": 2.8 },
    { "brand_name": "Coda", "total_mentions": 98, "avg_rank": 3.4 }
  ],
  "top_spot_ownership": [
    {
      "prompt": "What are the best CRM tools for enterprise?",
      "top_brand": "Notion",
      "count": 15
    }
  ],
  "primary_brand_cooccurrences": [
    { "competitor": "Coda", "count": 45, "primary_wins_pct": 68.5 }
  ]
}

Synthetic example. Values are made up.

API key required

60 req/min

Endpoint

GET/get-competitor-data

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Request parameters

brand_idstring | nullqueryOptional

Brand UUID

Format: uuid

brandstring | nullqueryOptional

Alias for brand_id

Format: uuid

viewstring | nullqueryOptional

View mode: summary (default), arena, head-to-head, by-model, threats, heatmap, over_time

competitorstring | nullqueryOptional

Competitor name. Required when view=head-to-head; on view=over_time it returns just you and that competitor.

daysintegerqueryOptional

History window every view is computed over. One of 7, 14, 30, 90.

Default: 30

tag_idsstring | nullqueryOptional

Comma-separated prompt tag UUIDs. Every metric in the response is recalculated over only the prompts carrying those tags, exactly as the Competitors page does when you filter by tag.

limitintegerqueryOptional

view=over_time only: how many competitor series to return, ranked best first.

Default: 10 · Minimum: 1 · Maximum: 50

periodstring | nullqueryOptional

A frozen calendar period instead of a rolling window: a month as YYYY-MM (2026-08) or a quarter as YYYY-Qn (2026-Q3). A closed month is read from the archive frozen when it closed; the open month is computed to date. When period is given, days is ignored and the response carries a `period` block saying exactly what was resolved. Definitions: /get-metrics.

Responses and errors
200Successful Response

application/json

CompetitorPeriodResponse

brandobjectRequired

periodobjectRequired

What a period-scoped response actually resolved.

Fields in period

keystringRequired

kindstringRequired

labelstringRequired

startstringRequired

endstringRequired

statusstringRequired

sourcestringRequired

frozen_atstring | nullOptional

pipeline_versionstring | nullOptional

restated_atstring | nullOptional

restatementsobject[]Optional

Default: []

Fields in restatements

Array of object. Default: []

object. Additional keys are allowed.

coverageobjectOptional

Default: {}

fields_computedstring[]Optional

Default: []

Fields in fields_computed

Array of string. Default: []

string.

fields_missingstring[]Optional

Default: []

Fields in fields_missing

Array of string. Default: []

string.

notesstring[]Optional

Default: []

Fields in notes

Array of string. Default: []

string.

monthsobject | nullOptional

rank_sourcestring | nullOptional

priorobject | nullOptional

Fields in prior
PeriodMeta

keystringRequired

kindstringRequired

labelstringRequired

startstringRequired

endstringRequired

statusstringRequired

sourcestringRequired

frozen_atstring | nullOptional

pipeline_versionstring | nullOptional

restated_atstring | nullOptional

restatementsobject[]Optional

Default: []

Fields in restatements

Array of object. Default: []

object. Additional keys are allowed.

coverageobjectOptional

Default: {}

fields_computedstring[]Optional

Default: []

Fields in fields_computed

Array of string. Default: []

string.

fields_missingstring[]Optional

Default: []

Fields in fields_missing

Array of string. Default: []

string.

notesstring[]Optional

Default: []

Fields in notes

Array of string. Default: []

string.

monthsobject | nullOptional

rank_sourcestring | nullOptional

null

null.

your_rankinteger | nullOptional

rank_poolinteger | nullOptional

your_visibilitynumber | nullOptional

your_visibility_avgnumber | nullOptional

your_rank_by_avginteger | nullOptional

your_visibility_by_avgnumber | nullOptional

competitorsobject[]Optional

Default: []

Fields in competitors

Array of object. Default: []

namestringRequired

rankinteger | nullOptional

visibilitynumber | nullOptional

is_youbooleanOptional

Default: false

prior_rankinteger | nullOptional

prior_visibilitynumber | nullOptional

positions_gainedinteger | nullOptional

visibility_deltanumber | nullOptional

new_in_listboolean | nullOptional

competitors_by_avgobject[]Optional

Default: []

Fields in competitors_by_avg

Array of object. Default: []

namestringRequired

rankinteger | nullOptional

visibilitynumber | nullOptional

is_youbooleanOptional

Default: false

prior_rankinteger | nullOptional

prior_visibilitynumber | nullOptional

positions_gainedinteger | nullOptional

visibility_deltanumber | nullOptional

new_in_listboolean | nullOptional

notable_changeobject | nullOptional

perception_competitorsobject[]Optional

Default: []

Fields in perception_competitors

Array of object. Default: []

object. Additional keys are allowed.

CompetitorDataResponse

brand_performance_summaryobject[]Required

Fields in brand_performance_summary

Array of object.

brand_namestringRequired

total_mentionsintegerRequired

avg_ranknumberRequired

top_spot_ownershipobject[]Required

Fields in top_spot_ownership

Array of object.

promptstringRequired

top_brandstringRequired

countintegerRequired

primary_brand_cooccurrencesobject[]Required

Fields in primary_brand_cooccurrences

Array of object.

competitorstringRequired

countintegerRequired

primary_wins_pctnumberRequired

filters_appliedobject | nullOptional

Fields in filters_applied
CompetitorFiltersApplied

daysintegerRequired

tag_idsstring[]Optional

Default: []

Fields in tag_ids

Array of string. Default: []

string.

prompts_in_scopeinteger | nullOptional

null

null.

CompetitorArenaResponse

promptsobject[]Required

Fields in prompts

Array of object.

prompt_textstringRequired

your_rankintegerRequired

your_scorenumber | nullOptional

leaderstringRequired

leader_scorenumber | nullOptional

gap_to_leadernumberRequired

total_competitorsintegerRequired

rankingsobject[]Required

Fields in rankings

Array of object.

rankintegerRequired

namestringRequired

scorenumberRequired

is_youbooleanOptional

Default: false

total_promptsintegerRequired

prompts_you_leadintegerRequired

prompts_top_3integerRequired

CompetitorH2HResponse

youobjectRequired

Fields in you

namestringRequired

visibilitynumberRequired

visibility_changenumber | nullOptional

avg_ranknumber | nullOptional

rank1_countintegerOptional

Default: 0

rivalobjectRequired

Fields in rival

namestringRequired

visibilitynumberRequired

visibility_changenumber | nullOptional

avg_ranknumber | nullOptional

rank1_countintegerOptional

Default: 0

head_to_headobjectRequired

Fields in head_to_head

your_winsintegerRequired

rival_winsintegerRequired

tiesintegerRequired

your_win_ratenumberRequired

total_matchupsintegerRequired

where_rival_winsobject[]Required

Fields in where_rival_wins

Array of object.

prompt_textstringRequired

your_rankintegerRequired

rival_rankintegerRequired

where_you_winobject[]Required

Fields in where_you_win

Array of object.

prompt_textstringRequired

your_rankintegerRequired

rival_rankintegerRequired

available_rivalsstring[]Required

Fields in available_rivals

Array of string.

string.

filters_appliedobject | nullOptional

Fields in filters_applied
CompetitorFiltersApplied

daysintegerRequired

tag_idsstring[]Optional

Default: []

Fields in tag_ids

Array of string. Default: []

string.

prompts_in_scopeinteger | nullOptional

null

null.

CompetitorByModelResponse

llmsstring[]Required

Fields in llms

Array of string.

string.

brandsstring[]Required

Fields in brands

Array of string.

string.

your_brandstringRequired

heatmapobject[]Required

Fields in heatmap

Array of object.

brandstringRequired

llmstringRequired

visibilitynumberRequired

avg_ranknumber | nullOptional

mentionsintegerRequired

is_youbooleanOptional

Default: false

insightsobject[]Required

Fields in insights

Array of object.

typestringRequired

llmstring | nullOptional

messagestringRequired

your_best_llmstring | nullOptional

your_worst_llmstring | nullOptional

CompetitorThreatsResponse

threatsobject[]Required

Fields in threats

Array of object.

competitorstringRequired

severitystringRequired

pressure_scorenumberRequired

win_rate_against_younumberRequired

cooccurrence_countintegerRequired

trendstringRequired

descriptionstringRequired

opportunitiesobject[]Required

Fields in opportunities

Array of object.

prompt_textstringRequired

your_rankintegerRequired

gap_to_nextnumberRequired

next_competitorstringRequired

opportunity_scorenumberRequired

categorystring | nullOptional

alertsobject[]Required

Fields in alerts

Array of object.

typestringRequired

severitystringRequired

messagestringRequired

promptstring | nullOptional

competitorstring | nullOptional

summaryobjectRequired

CompetitorHeatmapResponse

brandsstring[]Required

Fields in brands

Array of string.

string.

modelsstring[]Required

Fields in models

Array of string.

string.

your_brandstringRequired

cellsobject[]Required

Fields in cells

Array of object.

brandstringRequired

modelstringRequired

visibilitynumberRequired

avg_ranknumber | nullOptional

mentionsintegerOptional

Default: 0

is_youbooleanOptional

Default: false

your_best_modelstring | nullOptional

your_worst_modelstring | nullOptional

CompetitorOverTimeResponse

brandsobject[]Required

Fields in brands

Array of object.

namestringRequired

is_youbooleanOptional

Default: false

rankinteger | nullOptional

visibilitynumber | nullOptional

data_pointsobject[]Required

Fields in data_points

Array of object.

object. Additional keys are allowed.

period_daysintegerRequired

date_rangeobjectRequired

your_brandstring | nullOptional

data_throughstring | nullOptional

filters_appliedobject | nullOptional

Fields in filters_applied
CompetitorFiltersApplied

daysintegerRequired

tag_idsstring[]Optional

Default: []

Fields in tag_ids

Array of string. Default: []

string.

prompts_in_scopeinteger | nullOptional

null

null.

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source

The default response has exactly three keys: brand_performance_summary, top_spot_ownership and primary_brand_cooccurrences. Use the view parameter for the other shapes.

This endpoint is rate limited to 60 requests per minute per API key. See the Rate Limits page for handling 429 responses.
Frozen periods. Pass period=2026-08 (a month) or period=2026-Q3 (a quarter) to read this endpoint from the monthly archive instead of a rolling window. A closed month answers identically however later it is asked; the open month is computed to date and says status: open. When period is set, days is ignored and the response carries a period block. Only view=summary reads a period (400 otherwise), and the response takes a different shape: your_rank, rank_pool, your_visibility, competitors[] with prior_rank, positions_gained, visibility_delta and new_in_list, notable_change and perception_competitors. See Periods.
Try GET /get-competitor-data

Performance Summary

The brand_performance_summary array shows how you and your competitors rank overall. Your brand is always listed first, and up to 20 brands come back.

Top Spot Ownership

The top_spot_ownership array shows which brand "owns" the #1 position for each prompt. Use this to identify prompts where competitors dominate. Up to 10 prompts come back.

FieldDescription
promptThe prompt text
top_brandBrand most often in position #1
countTimes this brand was #1

Head-to-Head

The primary_brand_cooccurrences array shows how you perform when you and a competitor both appear in the same AI response. Up to 10 competitors come back, most co-occurrences first.

A primary_wins_pct above 50% means you typically rank higher than that competitor when you both appear. Below 50% means they usually beat you.

View Modes

Use the view parameter to access different competitive analysis views. Omitting it (or passing view=summary) returns the default response above.

ViewDescription
summaryDefault. Full competitive analysis with rankings and co-occurrences.
arenaPrompt-by-prompt battlegrounds with leaders, gaps, and rankings.
head-to-headDirect 1v1 comparison. Requires competitor parameter.
by-modelCompetitive breakdown per AI model.
threatsCompetitive threats, opportunity prompts, alerts, and summary counts.
heatmapBrand-by-model cells, plus your best and worst model.
over_timeDaily visibility per brand, for you and your competitors.
Any other value returns 400 with the list of valid views.

view=arena

Returns prompt-by-prompt battlegrounds. Each prompt includes your rank, the current leader, the gap to that leader, and the top competitor rankings.

Request
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=arena&days=30&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "prompts": [
    {
      "prompt_text": "best team knowledge base",
      "your_rank": 2,
      "your_score": 2.4,
      "leader": "Coda",
      "leader_score": 1.6,
      "gap_to_leader": 0.8,
      "total_competitors": 6,
      "rankings": [
        { "rank": 1, "name": "Coda", "score": 1.6, "is_you": false },
        { "rank": 2, "name": "Notion", "score": 2.4, "is_you": true }
      ]
    }
  ],
  "total_prompts": 45,
  "prompts_you_lead": 12,
  "prompts_top_3": 31
}

Synthetic example. Values are made up.

view=head-to-head

Returns a direct 1v1 comparison with a specific competitor. The competitor parameter is required and must match a competitor name (case-insensitive).

Request
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=head-to-head&competitor=Coda&days=30&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "you": {
    "name": "Notion",
    "visibility": 42.5,
    "visibility_change": 3.1,
    "avg_rank": 2.4,
    "rank1_count": 12
  },
  "rival": {
    "name": "Coda",
    "visibility": 36.2,
    "visibility_change": null,
    "avg_rank": 3.1,
    "rank1_count": 8
  },
  "head_to_head": {
    "your_wins": 18,
    "rival_wins": 10,
    "ties": 4,
    "your_win_rate": 0.56,
    "total_matchups": 32
  },
  "where_rival_wins": [
    {
      "prompt_text": "best document collaboration tools",
      "your_rank": 3,
      "rival_rank": 1
    }
  ],
  "where_you_win": [
    {
      "prompt_text": "best project management tools 2026",
      "your_rank": 1,
      "rival_rank": 4
    }
  ],
  "available_rivals": ["Coda", "Confluence", "Slite"]
}

Synthetic example. Values are made up.

Returns 400 if the competitor parameter is not provided, or 404 if the competitor is not found in your competitive set.

view=by-model

Returns competitive performance broken down by AI model (ChatGPT, Perplexity, Gemini, etc.). Useful for identifying which models favor your brand versus competitors.

Request
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=by-model&days=30&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "llms": ["ChatGPT", "Claude", "Perplexity"],
  "brands": ["Notion", "Coda", "Confluence"],
  "your_brand": "Notion",
  "heatmap": [
    {
      "brand": "Notion",
      "llm": "ChatGPT",
      "visibility": 48.2,
      "avg_rank": 2.4,
      "mentions": 45,
      "is_you": true
    }
  ],
  "insights": [
    { "type": "strength", "llm": "ChatGPT", "message": "You perform best on ChatGPT" }
  ],
  "your_best_llm": "ChatGPT",
  "your_worst_llm": "Gemini"
}

Synthetic example. Values are made up.

view=threats

Returns competitive threats, opportunity prompts, alerts, and summary counts.

Request
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=threats&days=30&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "threats": [
    {
      "competitor": "Coda",
      "severity": "high",
      "pressure_score": 0,
      "win_rate_against_you": 0.61,
      "cooccurrence_count": 32,
      "trend": "gaining",
      "description": "Wins 61% of 32 head-to-head matchups"
    }
  ],
  "opportunities": [
    {
      "prompt_text": "best CRM for startups",
      "your_rank": 0,
      "gap_to_next": 0,
      "next_competitor": "Coda",
      "opportunity_score": 6,
      "category": "comparison"
    }
  ],
  "alerts": [
    {
      "type": "threat",
      "severity": "high",
      "message": "Coda is gaining on comparison prompts",
      "prompt": "best team knowledge base",
      "competitor": "Coda"
    }
  ],
  "summary": {
    "total_threats": 1,
    "critical_threats": 0,
    "high_threats": 1,
    "total_opportunities": 1,
    "high_value_opportunities": 1
  }
}

Synthetic example. Values are made up.

pressure_score is not populated yet and always comes back as 0. Rank threats on severity, win_rate_against_you and cooccurrence_count instead.

view=over_time

Returns one daily visibility series per brand: yours first with is_you set to true, then your competitors ranked best first. This is the same data the Competitive Trend chart draws in the app.

The series is recomputed from stored daily results, so the full window is available the first time you call it. You do not need to accumulate history yourself.
Request
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=over_time&days=90&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "brands": [
    {
      "name": "Notion",
      "is_you": true,
      "rank": 1,
      "visibility": 41.1,
      "data_points": [
        { "date": "2026-05-02", "visibility": 38.2 },
        { "date": "2026-05-09", "visibility": 41.1 }
      ]
    },
    {
      "name": "Coda",
      "is_you": false,
      "rank": 2,
      "visibility": 36.4,
      "data_points": [
        { "date": "2026-05-02", "visibility": 34.9 },
        { "date": "2026-05-09", "visibility": 36.4 }
      ]
    }
  ],
  "period_days": 90,
  "date_range": { "start": "2026-05-02", "end": "2026-07-28" },
  "your_brand": "Notion",
  "data_through": "2026-07-28",
  "filters_applied": {
    "days": 90,
    "tag_ids": [],
    "prompts_in_scope": 42
  }
}

Synthetic example. Values are made up.

Scoping by window and tag

Every view accepts days and tag_ids. Passing tags recalculates every number in the response over only the prompts carrying those tags, so you can ask how a client compares inside one business line rather than across their whole prompt set. Tag UUIDs come from /get-tags.

Daily competitive position within one tag
curl -X GET 'https://api.trakkr.ai/get-competitor-data?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=over_time&days=90&tag_ids=00000000-0000-4000-8000-81f286d10c3c&limit=10' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Responses carry filters_applied so a tagged slice can never be mistaken for the brand's overall position. In view=head-to-head, the visibility_change field is null under a tag filter, because that movement is measured across the full prompt set.

days accepts 7, 14, 30 or 90. Any other value returns 400 with the supported list.

Use Cases

  • Identify your strongest and weakest competitive matchups
  • Find prompts where competitors dominate
  • Track competitive position over time with view=over_time
  • Report on one business line by passing tag_ids to any view
  • Prioritize content efforts based on competitive gaps
  • Compare performance by AI model with view=by-model
  • Detect emerging threats with view=threats