CitationBenchTalk to Sales
API referenceResearch

Research · Competitor API — Track Backlinks, Keywords & Overlap Matrices

Add competitors as first-class workspace resources, then pull their backlinks, ranking keywords, and keyword overlap matrices against your own library — the data layer behind gap analysis and outreach.

Track competitors and pull intelligence about them: their backlinks, the keywords they rank for, the keyword overlap matrix against your own library. Competitors are workspace-scoped first-class resources — you add them once, then any tool can reference them.

Conceptual overview

A competitor is a domain you're tracking against your workspace. Each adds three queryable data sources:

  • Backlinks — every site linking to the competitor (via Ahrefs), scored by domain quality and relevance to your offering
  • Keywords — every keyword the competitor ranks for, with position + estimated traffic
  • Overlap matrix — your keyword library × theirs; reveals what they have that you don't (and vice versa)

This is the data layer behind Link Building · competitor link outreach (turn competitor backlinks into your outreach targets) and Research · content gap (find topics they cover that you don't).

Endpoints

MethodPathPurpose
POST/v1/research/competitorAdd a competitor
GET/v1/research/competitorList tracked competitors
GET/v1/research/competitor/{id}Get one competitor + summary stats
PATCH/v1/research/competitor/{id}Update tags / notes / weight
DELETE/v1/research/competitor/{id}Stop tracking
POST/v1/research/competitor/{id}/backlinksPull / refresh backlink data
POST/v1/research/competitor/{id}/keywordsPull / refresh keyword data
GET/v1/research/competitor/{id}/backlinksList stored backlinks
GET/v1/research/competitor/{id}/keywordsList stored keywords
GET/v1/research/competitor/{id}/overlapKeyword overlap matrix vs. your workspace

POST /v1/research/competitor

curl -X POST https://api.citationbench.com/v1/research/competitor \
  -H "Authorization: Bearer sk_live_***" \
  -H "X-Workspace-Id: ws_acme" \
  -d '{
    "domain": "monday.com",
    "weight": "incumbent",
    "tags":   ["enterprise", "pm-category"],
    "notes":  "Primary incumbent in enterprise PM"
  }'
FieldTypeRequiredDefaultNotes
domainstringyesThe competitor's primary domain
weightenumno"alternative"incumbent, alternative, complementary, inspiration — drives how their data is used in scoring
tagsstring[]no
notesstringnoFree text

Response

{
  "id": "cmp_***",
  "domain": "monday.com",
  "weight": "incumbent",
  "tags": ["enterprise", "pm-category"],
  "stats": {
    "backlinks": null,
    "keywords": null,
    "lastBacklinkPullAt": null,
    "lastKeywordPullAt": null
  },
  "createdAt": "2026-05-24T08:01:00Z"
}

stats populates after you pull data via the sub-endpoints.


POST /v1/research/competitor/{id}/backlinks

Pulls fresh backlink data from Ahrefs and stores CompetitorPage + CompetitorKeyword records.

curl -X POST https://api.citationbench.com/v1/research/competitor/cmp_***/backlinks \
  -d '{
    "limit":          5000,
    "minDomainRating":30,
    "linkType":       "dofollow"
  }'
FieldNotes
limitMax backlinks to store (default 1000)
minDomainRatingFloor for DR (default 0)
linkTypedofollow, nofollow, all
countryFilter by linking domain country
freshnesscached returns the last pull; default refetches

Returns an invocationId. On completion, result includes counts and a sample.

{
  "result": {
    "pulled": 4247,
    "stored": 4108,
    "byDR": { "80+": 132, "60-79": 821, "40-59": 1947, "<40": 1208 },
    "byCountry": { "us": 2641, "uk": 481, "in": 312 }
  }
}

POST /v1/research/competitor/{id}/keywords

Pulls every keyword the competitor ranks for.

curl -X POST .../v1/research/competitor/cmp_***/keywords \
  -d '{
    "topPosition":    20,
    "minVolume":      100,
    "freshness":      "now"
  }'

Stores CompetitorKeyword + CompetitorKeywordRank records.


curl -G .../v1/research/competitor/cmp_***/backlinks \
  --data-urlencode "minDR=40" \
  --data-urlencode "relevance=high" \
  --data-urlencode "limit=100"
{
  "data": [
    {
      "id": "cbl_***",
      "sourceDomain": "engineering-blog.com",
      "sourceUrl": "https://engineering-blog.com/best-pm-tools",
      "targetUrl": "https://monday.com/features",
      "domainRating": 62,
      "linkType": "dofollow",
      "anchorText": "monday.com's project management",
      "relevanceScore": 0.84,
      "achievabilityScore": 0.71,
      "firstSeenAt": "2024-08-12",
      "lastSeenAt": "2026-05-15"
    }
  ],
  "nextCursor": null,
  "total": 4108
}

achievabilityScore is our heuristic for "how likely you could earn this link too" — based on domain authority, content type, prior outreach receptivity.


GET /v1/research/competitor/{id}/keywords

curl -G .../v1/research/competitor/cmp_***/keywords \
  --data-urlencode "topPosition=10" \
  --data-urlencode "limit=200"
{
  "data": [
    {
      "id": "ckw_***",
      "keyword": "project management software",
      "position": 1,
      "estimatedTraffic": 28400,
      "intent": "PURCHASE"
    }
  ],
  "total": 7281
}

GET /v1/research/competitor/{id}/overlap

Compute the keyword overlap matrix between your workspace and the competitor.

curl https://api.citationbench.com/v1/research/competitor/cmp_***/overlap
{
  "competitorId": "cmp_***",
  "competitorDomain": "monday.com",
  "summary": {
    "competitorKeywords": 7281,
    "ourKeywords": 612,
    "shared": 184,
    "competitorOnly": 7097,
    "ourOnly": 428,
    "overlapRatio": 0.3
  },
  "topGaps": [
    {
      "keyword": "engineering capacity tracking",
      "competitorRank": 8,
      "ourRank": null,
      "volume": 540
    },
    {
      "keyword": "sprint planning for distributed teams",
      "competitorRank": 4,
      "ourRank": null,
      "volume": 720
    }
  ],
  "topWins": [
    {
      "keyword": "open source project management",
      "ourRank": 6,
      "competitorRank": 42,
      "volume": 280
    }
  ]
}

MCP

> Add monday.com as a competitor and pull their keywords + backlinks.

Claude calls research.competitor.add, then research.competitor.keywords, then research.competitor.backlinks.

> What keywords does monday.com rank for that we don't?

Claude calls research.competitor.overlap and renders the topGaps.


Errors

StatusCodeCause
400validation_errorMissing / malformed domain
409competitor_existsAlready tracking
503ahrefs_unavailableBacklink pull failed
503dataforseo_unavailableKeyword pull failed

Cost

ActionCredits
POST /v1/research/competitorfree
POST /backlinks30 (one-time pull; refresh costs 30)
POST /keywords20
GET /overlap2 (computed on demand)
All other GETsfree

Use cases (string things together)

A. Steal-from-competitor outreach

# 1. Track + pull
COMP=$(curl -sf -X POST .../v1/research/competitor -d '{"domain":"monday.com"}' | jq -r '.id')
curl -X POST .../v1/research/competitor/$COMP/backlinks

# 2. Pitch our content to the same backlink sources
curl -X POST .../v1/link-building/competitor-outreach -d "{
  \"competitorId\":  \"$COMP\",
  \"ourContentUrl\": \"https://acme.com/blog/engineering-team-capacity-tracking\",
  \"minDR\":         40
}"

B. Content gap surface

# 1. Build keyword universe
curl -X POST .../v1/research/keyword -d '{"seed":"project management software"}'

# 2. Add 3 competitors
for D in monday.com asana.com clickup.com; do
  curl -X POST .../v1/research/competitor -d "{\"domain\":\"$D\"}"
done

# 3. Pull each one's keywords
# 4. Run overlap → content gap report
curl -X POST .../v1/research/content-gap -d '{
  "competitorIds": ["cmp_A", "cmp_B", "cmp_C"]
}'

C. Continuous monitoring

# Weekly refresh of competitor keywords
curl -X POST .../v1/agent/invoke -d '{
  "skill": "agent.scheduled",
  "input": {
    "action":  "research.competitor.keywords",
    "schedule":"weekly:sun:18:00",
    "config":  { "competitorId": "cmp_***" }
  }
}'

On this page