Competitor link outreach API — automate replacement-link campaigns from a competitor domain
Seed a campaign with a competitor domain. The agent pulls their backlinks via Ahrefs, filters for quality and relevance, discovers contacts, and drafts personalized outreach pitching your content as a parallel option.
Sibling endpoint to SERP outreach. Instead of a SERP, the seed is a competitor domain — CitationBench pulls every site linking to the competitor (via Ahrefs), filters for quality and relevance, discovers contacts, and drafts outreach pitching your content as a parallel/replacement option.
Same downstream model as SERP outreach: drafts park at WAITING_APPROVAL, you approve in bulk, sends fire via Instantly.
Conceptual overview
For each competitor backlink, the agent reasons:
- Is this site a content site (where they linked to a resource) or a transactional site? (We pitch content sites.)
- Does our content match the angle they're already endorsing? (Higher hit rate.)
- Has anyone in our CRM already pitched this site? (Skip if recent.)
- Is the site's DR high enough to be worth our time?
The drafted email cites the existing competitor link explicitly: "You mentioned [competitor]'s capacity tracking — we just published a different take that ...".
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/link-building/competitor-outreach | Start a competitor outreach campaign |
| GET | /v1/link-building/competitor-outreach | List campaigns |
| GET | /v1/link-building/competitor-outreach/{id} | Get one campaign |
| GET | /v1/link-building/competitor-outreach/{id}/drafts | List drafts |
| POST | /v1/link-building/competitor-outreach/{id}/approve | Bulk approve |
| POST | /v1/link-building/competitor-outreach/{id}/reject | Bulk reject |
| PATCH | /v1/link-building/competitor-outreach/{id} | Adjust filters / pause |
| DELETE | /v1/link-building/competitor-outreach/{id} | Cancel |
POST /v1/link-building/competitor-outreach
{
"competitorId": "cmp_monday",
"ourContentUrl": "https://acme.com/blog/engineering-team-capacity-tracking",
"filters": {
"minDomainRating": 40,
"maxDomainRating": 85,
"linkType": "dofollow",
"minRelevanceScore": 0.7,
"minAchievabilityScore": 0.5,
"excludeAlreadyContactedWithinDays": 180,
"limit": 25
},
"outreach": {
"targetingAngle": "parallel_resource",
"emailTemplate": "tpl_competitor-replacement",
"personalize": true,
"approval": { "required": true }
},
"tags": ["q2-2026"]
}| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
competitorId | string | yes | — | A tracked competitor (see Research · competitor) |
competitorDomain | string | one of | — | Or raw domain (auto-creates competitor record) |
ourContentUrl | string | yes | — | The asset you want to pitch as a parallel resource |
filters.minDomainRating / maxDomainRating | number | no | 40 / 85 | — |
filters.linkType | enum | no | dofollow | dofollow, nofollow, all |
filters.minRelevanceScore | number | no | 0.7 | Topical relevance of the linking page to your content |
filters.minAchievabilityScore | number | no | 0.5 | Heuristic for how likely you could earn the link too |
filters.excludeAlreadyContactedWithinDays | number | no | 180 | — |
filters.limit | number | no | 25 | Cap on accounts to pitch |
outreach.targetingAngle | enum | no | link_insertion | link_insertion, parallel_resource, replacement, update_outdated_link |
outreach.emailTemplate | string | no | workspace default | — |
outreach.approval.required | boolean | no | workspace policy | — |
Response
{
"campaignId": "ccmp_***",
"invocationId": "inv_***",
"agentId": "agt_***",
"skill": "link_building.competitor_outreach",
"status": "RUNNING",
"estimatedCost": { "credits": 32, "durationSeconds": 360 }
}Final summary
{
"campaignId": "ccmp_***",
"invocationId": "inv_***",
"agentId": "agt_***",
"skill": "link_building.competitor_outreach",
"status": "AWAITING_APPROVAL",
"creditsUsed": 30,
"summary": {
"competitorBacklinks": 4108,
"afterLinkTypeFilter": 2841,
"afterDomainRatingFilter": 1217,
"afterRelevanceFilter": 412,
"afterAchievabilityFilter": 178,
"afterAlreadyContactedFilter": 91,
"afterContactDiscovery": 27,
"finalDrafts": 25
},
"topDomains": [
{
"domain": "engineering-blog.com",
"drafted": true,
"domainRating": 62,
"relevanceScore": 0.84,
"achievabilityScore": 0.71
}
],
"raw": "Pulled 4,108 backlinks for monday.com. Filtered to 25 high-relevance, high-achievability content sites that don't currently link to us ...",
"files": [
"agent-workspace/backlinks-raw.json",
"agent-workspace/filter-decisions.csv",
"agent-output/drafts.md"
]
}GET /v1/link-building/competitor-outreach/{id}/drafts
Same shape as SERP outreach drafts — each draft has relationshipId, accountId, contact, subject, body, status, approvalUrl.
POST /v1/link-building/competitor-outreach/{id}/approve
Same shape as SERP outreach approve.
curl -X POST .../v1/link-building/competitor-outreach/ccmp_***/approve -d '{
"draftIds": "all",
"scheduleAt": "2026-05-25T09:00:00-04:00"
}'MCP
> Pull monday.com's backlinks and pitch our capacity-tracking article to the best 25 sources.Claude calls link_building.competitor_outreach.create.
> Show the drafts; let me approve them.Claude calls link_building.competitor_outreach.drafts + approval loop.
Errors
| Status | Code | Cause |
|---|---|---|
| 404 | competitor_not_found | — |
| 422 | no_backlinks_found | Competitor has no usable backlinks (try refreshing) |
| 422 | no_drafts_produced | All backlinks filtered out — loosen filters |
| 503 | ahrefs_unavailable | — |
| 503 | apollo_unavailable | — |
Cost
| Action | Credits |
|---|---|
| Per campaign (per 25-draft cap) | ~30 |
| + per-domain contact discovery (Apollo) | +0.4 each |
| + per-draft LLM personalization | +0.5 each |
| + per email sent on approval | +2 each |
Use cases (string things together)
A. Steal-from-competitor weekly
for CMP in cmp_monday cmp_asana cmp_clickup; do
curl -X POST .../v1/link-building/competitor-outreach -d "{
\"competitorId\": \"$CMP\",
\"ourContentUrl\": \"https://acme.com/blog/engineering-team-capacity-tracking\"
}"
doneB. Replacement angle when a competitor has a broken link
curl -X POST .../v1/link-building/competitor-outreach -d '{
"competitorId": "cmp_monday",
"ourContentUrl": "https://acme.com/blog/our-replacement-article",
"outreach": { "targetingAngle": "replacement" }
}'The drafted email surfaces the specific broken link as the hook.
C. Run as part of the link_hunter skill
curl -X POST .../v1/agent/invoke -d '{
"skill": "link_hunter",
"input": {
"competitorIds": ["cmp_monday"],
"ourContentUrls": ["https://acme.com/blog/engineering-team-capacity-tracking"],
"cadence": "weekly"
}
}'Related
- API: Link Building · serp outreach — sibling
- API: Link Building · inbound — the inverse
- API: Link Building · campaign management
- API: Link Building · CRM
- API: Research · competitor
- Concept: Link Building
SERP outreach
Turn a single keyword into a fully scoped outreach campaign. Fetches the top SERP, filters junk, discovers contacts, drafts personalized emails, and parks the campaign at WAITING_APPROVAL for review.
Inbound
An autonomous negotiator that handles inbound link-building emails on your behalf. Drafts (and optionally sends) replies to negotiate swaps, paid placements, guest posts, and insertions — with eval gates that escalate to a human.