Research · Content Gap API — Find Missing Topics, Keyword Gaps & Weaker Coverage vs. Competitors
Compare your content library against competitor coverage to surface missing topics, keyword gaps, and weaker pages — ranked by lift with suggested briefs ready to queue into bulk content production.
Given your content library + a competitor URL list, find the topics they cover that you don't, the keywords they rank for where you don't, and the topics where their content is materially better.
The output is a ranked gap report with suggested content briefs — straightforward to feed into produce.blog_post.bulk.
Conceptual overview
A content-gap analysis compares:
- Your content — every published BlogPost + LandingPage in the workspace
- Competitor coverage — pages on the competitor domains (crawled and embedded)
- Keyword surfaces — where each side ranks
It produces three gap types:
| Gap type | Meaning |
|---|---|
MISSING_TOPIC | They have a piece on this topic; you have nothing |
KEYWORD_GAP | They rank for these keywords; you have no content targeting them |
WEAKER_COVERAGE | You have something but theirs ranks better (depth, freshness, links) |
Each gap comes with a recommended angle and an estimated lift.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/research/content-gap | Run a gap analysis |
| GET | /v1/research/content-gap | List recent reports |
| GET | /v1/research/content-gap/{id} | Get one report |
| POST | /v1/research/content-gap/{id}/queue-content | Auto-create blog posts / landing pages for the report's gaps |
POST /v1/research/content-gap
Request
POST /v1/research/content-gap HTTP/1.1
Authorization: Bearer sk_live_***
X-Workspace-Id: ws_acme
{
"competitorIds": ["cmp_monday", "cmp_asana", "cmp_linear"],
"options": {
"includeWeakerCoverage": true,
"maxGapsPerType": 25,
"minCompetitorRank": 20,
"minKeywordVolume": 100,
"considerOwnedSubdomains":true
},
"tags": ["q2-2026"]
}| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
competitorIds | string[] | yes (one of) | — | Competitor IDs (see Research · competitor) |
competitorDomains | string[] | yes (one of) | — | Or raw domains (auto-creates competitor records) |
options.includeWeakerCoverage | boolean | no | true | — |
options.maxGapsPerType | number | no | 25 | — |
options.minCompetitorRank | number | no | 20 | Skip very deep results |
options.minKeywordVolume | number | no | 100 | Skip low-volume |
options.pillarFilter | string[] | no | — | Limit gaps to specific pillars |
Response (final)
{
"invocationId": "inv_***",
"agentId": "agt_***",
"skill": "research.content_gap",
"status": "SUCCEEDED",
"creditsUsed": 28,
"result": {
"reportId": "gap_***",
"competitorsAnalyzed": ["cmp_monday", "cmp_asana", "cmp_linear"],
"summary": {
"missingTopics": 17,
"keywordGaps": 82,
"weakerCoverage": 11,
"totalRecommendations": 110
},
"gaps": [
{
"id": "gap_item_***",
"type": "MISSING_TOPIC",
"topic": "Capacity forecasting for engineering teams",
"competitorsCovering": [
{
"competitorId": "cmp_monday",
"url": "https://monday.com/blog/capacity-forecasting"
}
],
"relatedKeywords": [
"capacity forecasting",
"engineering capacity planning"
],
"estimatedTraffic": 1240,
"recommendedAngle": "Tie capacity forecasting to sprint planning specifically — the existing content treats them separately.",
"estimatedLiftMonths": 4,
"priority": "HIGH"
},
{
"id": "gap_item_***",
"type": "KEYWORD_GAP",
"keyword": "monday.com vs linear",
"competitorsRanking": [
{ "competitorId": "cmp_monday", "position": 1 },
{ "competitorId": "cmp_linear", "position": 3 }
],
"estimatedTraffic": 480,
"recommendedAngle": "Write a 3-way comparison adding our take.",
"priority": "MEDIUM"
},
{
"id": "gap_item_***",
"type": "WEAKER_COVERAGE",
"ourContentId": "bp_***",
"ourRank": 14,
"competitorRank": 2,
"competitorUrl": "https://monday.com/blog/best-pm-tools",
"weaknessReason": "Ours: 1,800 words, 2 references. Theirs: 3,200 words, 14 references.",
"recommendedAction": "Refresh with more depth + add fresh case study",
"priority": "HIGH"
}
]
},
"raw": "Compared your content library against 3 competitors. Found 17 missing topics, 82 keyword gaps, 11 weaker-coverage cases. The biggest opportunities are around capacity forecasting and Linear comparisons ...",
"files": ["agent-workspace/coverage-matrix.csv", "agent-output/gap-report.md"]
}POST /v1/research/content-gap/{id}/queue-content
Turn the gaps into actual draft work in one call.
curl -X POST .../v1/research/content-gap/gap_***/queue-content -d '{
"selectGaps": [
{ "type": "MISSING_TOPIC", "priority": ["HIGH"] },
{ "type": "WEAKER_COVERAGE", "priority": ["HIGH"] }
],
"blogPostDefaults": {
"pillarSlug": "performance",
"mode": "with-research",
"refinerIds": ["rfn_brand-voice"]
},
"landingPageDefaults": {
"pillarSlug": "pricing"
}
}'The system spawns one produce.blog_post.create or produce.landing_page.create invocation per matched gap. Returns the batch handle.
{
"batchId": "batch_***",
"queued": {
"blogPosts": 17,
"landingPages": 4
},
"totalEstimatedCost": { "credits": 587 }
}GET /v1/research/content-gap
curl -G .../v1/research/content-gap \
--data-urlencode "tag=q2-2026" \
--data-urlencode "limit=20"GET /v1/research/content-gap/{id}
Returns the full report.
MCP
> Find content gaps between us and monday.com, asana.com, linear.app.Claude calls research.content_gap.find.
> Queue blog posts for the high-priority missing-topic gaps from that report.Claude calls research.content_gap.queue_content.
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | validation_error | Need competitorIds or competitorDomains |
| 422 | no_gaps_found | Coverage is comparable; nothing significant |
| 503 | external_unavailable | Ahrefs / DataForSEO down during analysis |
Cost
| Action | Credits |
|---|---|
POST /v1/research/content-gap per competitor | ~10 |
queue-content per content item spawned | per the underlying produce.* skill |
Use cases (string things together)
A. Quarterly gap audit
# Quarterly cron
curl -X POST .../v1/research/content-gap -d '{
"competitorIds": ["cmp_monday", "cmp_asana", "cmp_linear"],
"tags": ["q2-2026", "quarterly-audit"]
}'B. Auto-content from gaps
GAP=$(curl -sf -X POST .../v1/research/content-gap -d '{...}' | jq -r '.invocationId')
# (wait)
curl -X POST .../v1/research/content-gap/$GAP/queue-content -d '{...}'C. Cross-portfolio agency view
curl -X POST .../v1/workspaces/bulk-action -d '{
"action": "research.content_gap.find",
"workspaces": "all",
"config": { "competitorIds": "{{ workspace.competitors.top_3 }}" }
}'One call → one gap report per client workspace.
Related
- API: Research · competitor
- API: Research · keyword
- API: Production · blog post
- API: Production · landing page
- Playbook: From competitor URL to content plan
AI citation
CitationBench's AI citation tracking API monitors when ChatGPT, Perplexity, Claude, Gemini, and Google AI Overviews cite your domain or competitors — per prompt, per LLM, per day with variance smoothing.
Blog post
REST API for generating, editing, and managing AI-written blog posts. Supports quick, research-backed, and deep-technical generation modes with multi-step refinement chains and bulk workflows.