Developer Documentation
Competitor Monitoring API Reference
The RivalCheck competitive intelligence API gives you programmatic access to every piece of data the platform captures: competitor profiles, website change feeds, AI-powered analysis, battle cards, and landscape overviews. Whether you are building a Slack bot that alerts your sales team to competitor pricing changes, feeding data into an internal BI tool, or powering an AI agent that generates weekly competitive briefings, this API is your foundation.
This is a REST API that returns JSON. All endpoints require authentication via Bearer token. Dates use ISO 8601 format. The base URL for all requests is https://app.rivalcheck.com.
Why Automate Competitive Intelligence via API
Competitive intelligence, the practice of gathering, analyzing, and acting on information about your market rivals, has historically been a manual, time-consuming process. Teams assign analysts to review competitor websites weekly, compile pricing spreadsheets, and manually update battle cards that go stale within days. A competitor monitoring API changes this dynamic entirely.
With the RivalCheck competitor tracking API, you can:
- Detect pricing changes within hours instead of discovering them weeks later during lost deals. Our pricing change detection API continuously monitors competitor pricing pages and flags modifications with severity ratings.
- Feed real-time competitor data into AI workflows. Use the API or our MCP integration to let Claude, GPT, or custom LLM agents access competitive intelligence directly, enabling automated briefing generation, deal support, and strategic analysis.
- Keep battle cards perpetually current. The battle card API generates and regenerates competitive battle cards using the latest data, so your sales team always has fresh talking points.
- Build custom dashboards and alerts. Pull competitor data into your existing tools (Salesforce, HubSpot, Notion, internal BI) instead of forcing teams to log in to yet another platform.
- Create an audit trail of competitive moves. Every change is timestamped, categorized, and preserved with before/after snapshots. The competitor analysis API provides the raw materials for quarterly competitive reviews and board presentations.
Quick Start
1. Get your API key
Navigate to your Settings page and generate an API key. Keys begin with rc_live_ and are scoped to your organisation. You can revoke and regenerate keys at any time. If you do not have an account yet, sign up free.
2. Make your first request
List all competitors you are monitoring:
curl -H "Authorization: Bearer rc_live_YOUR_KEY" \ https://app.rivalcheck.com/api/v1/competitors
Authentication
All requests to the RivalCheck competitor monitoring API must include a valid API key in the Authorization header using the Bearer scheme.
Authorization: Bearer rc_live_abc123def456ghi789...
Key management
- API keys are generated in your account settings.
- Each key is scoped to a single organisation. All data returned is limited to that organisation's competitors and changes.
- Keys always start with
rc_live_. There are no sandbox/test keys; use a staging organisation for development. - You can revoke a key instantly from the settings page. A revoked key returns
401 Unauthorizedimmediately. - Treat your API key like a password. Never commit it to source control. Use environment variables in your applications.
Security tip: If you suspect a key has been compromised, revoke it immediately and generate a new one. Revocation takes effect within seconds.
Rate Limiting
The competitive intelligence API enforces a daily rate limit to ensure fair usage and platform stability. Limits are applied per API key (per organisation).
Current limits
| Plan | Daily Limit | Reset |
|---|---|---|
| All plans | 1,000 requests/day | Midnight UTC |
Response headers
Every API response includes rate limit information in the following headers:
| Header | Description | Example |
|---|---|---|
| X-RateLimit-Limit | Maximum requests allowed per day | 1000 |
| X-RateLimit-Remaining | Requests remaining in the current window | 847 |
| Retry-After | Seconds until the limit resets (only present on 429 responses) | 3600 |
Handling rate limits gracefully
When you exceed the daily limit, the API returns a 429 Too Many Requests status with a Retry-After header indicating how many seconds to wait. Best practices:
- Check
X-RateLimit-Remainingproactively and throttle when it drops below a threshold (e.g., 50). - Implement exponential backoff when you receive a 429. Start with the
Retry-Aftervalue, then double on each subsequent retry. - Cache responses where possible. Competitor profiles and battle cards change infrequently; the change feed is where freshness matters most.
- Use webhooks instead of polling. Webhooks do not count against your rate limit and deliver data in real time.
Example 429 response
{
"error": {
"code": "rate_limited",
"message": "Daily API limit exceeded. Resets at midnight UTC.",
"retry_after": 3600
}
}
Pagination
All list endpoints return paginated results. Pagination is controlled by two query parameters and described by a meta object in every response.
Request parameters
| Parameter | Type | Default | Constraints |
|---|---|---|---|
| page | integer | 1 | Minimum 1 |
| limit | integer | 25 | Minimum 1, maximum 100 |
Response meta object
Every paginated response wraps results in a data array and includes a meta object:
{
"data": [ ... ],
"meta": {
"page": 2,
"limit": 25,
"total": 73,
"total_pages": 3
}
}
Iterating through all pages
To retrieve all records, keep incrementing page until page equals total_pages. Example in Python:
import requests
all_changes = []
page = 1
while True:
resp = requests.get(
"https://app.rivalcheck.com/api/v1/changes",
headers={"Authorization": "Bearer rc_live_YOUR_KEY"},
params={"page": page, "limit": 100}
)
data = resp.json()
all_changes.extend(data["data"])
if page >= data["meta"]["total_pages"]:
break
page += 1
print(f"Fetched {len(all_changes)} total changes")
Error Handling
The API uses standard HTTP status codes. Error responses always include a JSON body with an error object containing a machine-readable code and a human-readable message.
Error response format
{
"error": {
"code": "not_found",
"message": "Competitor with ID 'comp_abc123' was not found."
}
}
Error codes reference
| HTTP Status | Error Code | Description | Common Cause |
|---|---|---|---|
| 401 | unauthorized | Authentication failed | Missing, invalid, or revoked API key |
| 404 | not_found | Resource not found | Invalid competitor or change ID, or resource belongs to a different organisation |
| 422 | validation_failed | Invalid request parameters | Missing required fields, invalid URL format, invalid filter values |
| 422 | limit_reached | Plan limit exceeded | Attempting to add more competitors than your plan allows |
| 429 | rate_limited | Too many requests | Daily rate limit exceeded; check Retry-After header |
Validation error example
When creating a competitor with an invalid URL, you receive detailed field-level errors:
// POST /api/v1/competitors { "website_url": "not-a-url" }
// 422 Unprocessable Entity
{
"error": {
"code": "validation_failed",
"message": "Validation failed for 1 field.",
"details": {
"website_url": ["must be a valid URL starting with http:// or https://"]
}
}
}
Plan limit error example
// POST /api/v1/competitors { "website_url": "https://newrival.com" }
// 422 Unprocessable Entity
{
"error": {
"code": "limit_reached",
"message": "Your Starter plan allows up to 5 competitors. Upgrade to add more.",
"current": 5,
"limit": 5,
"upgrade_url": "https://app.rivalcheck.com/app/billing"
}
}
API Endpoints
Complete reference for every endpoint in the RivalCheck competitor tracking API.
/api/v1/competitors
List Competitors
Returns a paginated list of all competitors your organisation is monitoring. This is typically the starting point for any integration with the competitor monitoring API: fetch your competitor list, then drill into changes or battle cards for each.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| status | string | all | Filter by status. One of: pending, discovering, active, paused, error, review_pages |
| page | integer | 1 | Page number (min 1) |
| limit | integer | 25 | Results per page (min 1, max 100) |
Response
{
"data": [
{
"id": "comp_8xKm2Nq",
"name": "Acme Corp",
"website_url": "https://www.acmecorp.com",
"status": "active",
"pages_count": 4,
"changes_count": 17,
"last_checked_at": "2026-03-24T06:15:00Z",
"last_change_at": "2026-03-22T14:33:00Z",
"has_battle_card": true,
"created_at": "2026-02-10T09:00:00Z"
},
{
"id": "comp_3pRtYvW",
"name": "BetaRival",
"website_url": "https://betarival.io",
"status": "active",
"pages_count": 3,
"changes_count": 8,
"last_checked_at": "2026-03-24T06:20:00Z",
"last_change_at": "2026-03-19T10:05:00Z",
"has_battle_card": true,
"created_at": "2026-02-15T11:30:00Z"
},
{
"id": "comp_9dLwZxJ",
"name": "NewStart.io",
"website_url": "https://newstart.io",
"status": "discovering",
"pages_count": 0,
"changes_count": 0,
"last_checked_at": null,
"last_change_at": null,
"has_battle_card": false,
"created_at": "2026-03-24T08:00:00Z"
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 3,
"total_pages": 1
}
}
Competitor statuses explained
| pending | Just created. Discovery has not started yet. |
| discovering | RivalCheck is crawling the website to identify key pages (pricing, product, about, etc.). |
| review_pages | Discovery is complete. Pages have been suggested and are awaiting your review before monitoring begins. |
| active | Actively monitored. Pages are checked regularly and changes are detected automatically. |
| paused | Monitoring paused by user. No checks are performed. Historical data is retained. |
| error | An error occurred during discovery or monitoring (e.g., site unreachable, blocked by firewall). |
/api/v1/competitors/:id
Get Competitor Detail
Returns the full profile of a single competitor, including all monitored pages, the five most recent changes, and battle card availability. This endpoint is ideal for building competitor detail views in custom dashboards or for feeding context to an AI agent preparing a sales call briefing.
Path parameters
| id | string, required | The competitor's public ID (e.g., comp_8xKm2Nq) |
Response
{
"data": {
"id": "comp_8xKm2Nq",
"name": "Acme Corp",
"website_url": "https://www.acmecorp.com",
"status": "active",
"last_checked_at": "2026-03-24T06:15:00Z",
"last_change_at": "2026-03-22T14:33:00Z",
"has_battle_card": true,
"battle_card_generated_at": "2026-03-20T12:00:00Z",
"created_at": "2026-02-10T09:00:00Z",
"pages": [
{
"id": "page_Kx8mNq2",
"url": "https://www.acmecorp.com/pricing",
"page_type": "pricing",
"last_checked_at": "2026-03-24T06:15:00Z",
"last_change_at": "2026-03-22T14:33:00Z",
"changes_count": 5
},
{
"id": "page_Rt3pYvW",
"url": "https://www.acmecorp.com/product",
"page_type": "product",
"last_checked_at": "2026-03-24T06:15:00Z",
"last_change_at": "2026-03-15T09:20:00Z",
"changes_count": 7
},
{
"id": "page_Lw9dZxJ",
"url": "https://www.acmecorp.com/about",
"page_type": "about",
"last_checked_at": "2026-03-24T06:15:00Z",
"last_change_at": "2026-03-01T16:45:00Z",
"changes_count": 3
},
{
"id": "page_Qn7bMvF",
"url": "https://www.acmecorp.com/enterprise",
"page_type": "landing",
"last_checked_at": "2026-03-24T06:15:00Z",
"last_change_at": "2026-03-18T11:10:00Z",
"changes_count": 2
}
],
"recent_changes": [
{
"id": "chg_Xp4kLm8",
"change_type": "pricing",
"severity": "major",
"summary": "Enterprise tier price increased from $299/mo to $349/mo. New 'Scale' tier added at $199/mo.",
"detected_at": "2026-03-22T14:33:00Z"
},
{
"id": "chg_Yn5jKn9",
"change_type": "content",
"severity": "moderate",
"summary": "Product page updated with new AI features section. Three new feature cards added highlighting 'AI Assistant', 'Smart Reports', and 'Predictive Analytics'.",
"detected_at": "2026-03-15T09:20:00Z"
}
]
}
}
/api/v1/competitors
Add a Competitor
Start monitoring a new competitor. RivalCheck will automatically crawl the website, identify key pages (pricing, product, about, blog, etc.), and begin monitoring them for changes. The competitor begins in pending status and progresses through discovering before becoming active. This process typically takes 1-3 minutes.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| website_url | string | Yes | Full URL of the competitor's website. Must start with http:// or https://. |
| name | string | No | Display name. If omitted, RivalCheck extracts the company name from the website automatically. |
Request example
curl -X POST https://app.rivalcheck.com/api/v1/competitors \
-H "Authorization: Bearer rc_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"website_url": "https://www.newrival.com",
"name": "NewRival"
}'
Response (201 Created)
{
"data": {
"id": "comp_Hk7nRt4",
"name": "NewRival",
"website_url": "https://www.newrival.com",
"status": "pending",
"pages_count": 0,
"changes_count": 0,
"last_checked_at": null,
"last_change_at": null,
"has_battle_card": false,
"created_at": "2026-03-24T10:30:00Z"
},
"message": "Competitor added. Discovery will begin shortly."
}
Tip: After creating a competitor, poll GET /api/v1/competitors/:id to check when the status transitions to active. Alternatively, configure a webhook for the competitor.status_changed event.
/api/v1/competitors/:id/changes
List Competitor Changes
Returns a paginated, filterable list of all changes detected for a specific competitor. Use this when you need a focused view of a single rival's activity, for example when preparing for a deal against that competitor or building a competitor-specific report.
Path parameters
| id | string, required | The competitor's public ID |
Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
| severity | string | all | Filter by severity: minor, moderate, major |
| type | string | all | Filter by change type: pricing, content, layout |
| since | string | none | ISO 8601 datetime. Only return changes detected after this timestamp. Example: 2026-03-01T00:00:00Z |
| page | integer | 1 | Page number |
| limit | integer | 25 | Results per page (max 100) |
Response
{
"data": [
{
"id": "chg_Xp4kLm8",
"competitor_id": "comp_8xKm2Nq",
"competitor_name": "Acme Corp",
"page_url": "https://www.acmecorp.com/pricing",
"page_type": "pricing",
"change_type": "pricing",
"severity": "major",
"summary": "Enterprise tier price increased from $299/mo to $349/mo. New 'Scale' tier added at $199/mo.",
"detected_at": "2026-03-22T14:33:00Z",
"reviewed": false,
"bookmarked": false
},
{
"id": "chg_Yn5jKn9",
"competitor_id": "comp_8xKm2Nq",
"competitor_name": "Acme Corp",
"page_url": "https://www.acmecorp.com/product",
"page_type": "product",
"change_type": "content",
"severity": "moderate",
"summary": "Product page updated with new AI features section. Three new feature cards added.",
"detected_at": "2026-03-15T09:20:00Z",
"reviewed": true,
"bookmarked": false
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 17,
"total_pages": 1
}
}
/api/v1/changes
List All Changes (Organisation-Wide Feed)
Returns a unified, paginated feed of changes across all competitors in your organisation. This is the most powerful endpoint in the competitive intelligence API for building dashboards, generating weekly briefings, or feeding a CI aggregation pipeline. Supports filtering by severity, type, competitor, date range, and full-text search.
Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
| severity | string | all | minor, moderate, or major |
| type | string | all | pricing, content, or layout |
| competitor_id | string | none | Filter to a specific competitor's public ID |
| since | string | none | ISO 8601 datetime. Only changes after this timestamp. |
| search | string | none | Full-text search across change summaries and AI analysis. Example: price increase |
| page | integer | 1 | Page number |
| limit | integer | 25 | Results per page (max 100) |
Example: Fetch major pricing changes from the past 7 days
curl -G https://app.rivalcheck.com/api/v1/changes \ -H "Authorization: Bearer rc_live_YOUR_KEY" \ -d severity=major \ -d type=pricing \ -d since=2026-03-17T00:00:00Z
Response
{
"data": [
{
"id": "chg_Xp4kLm8",
"competitor_id": "comp_8xKm2Nq",
"competitor_name": "Acme Corp",
"page_url": "https://www.acmecorp.com/pricing",
"page_type": "pricing",
"change_type": "pricing",
"severity": "major",
"summary": "Enterprise tier price increased from $299/mo to $349/mo. New 'Scale' tier added at $199/mo.",
"detected_at": "2026-03-22T14:33:00Z",
"reviewed": false,
"bookmarked": false
},
{
"id": "chg_Bm2wQt7",
"competitor_id": "comp_3pRtYvW",
"competitor_name": "BetaRival",
"page_url": "https://betarival.io/pricing",
"page_type": "pricing",
"change_type": "pricing",
"severity": "major",
"summary": "Free tier removed entirely. Lowest plan now starts at $29/mo (previously had a free plan with 100 API calls).",
"detected_at": "2026-03-19T10:05:00Z",
"reviewed": true,
"bookmarked": true
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 2,
"total_pages": 1
}
}
Change types and severity levels
Change types
| pricing | Price adjustments, new tiers, removed plans, trial changes |
| content | Copy changes, new features, messaging shifts, positioning updates |
| layout | Visual redesigns, new sections, structural reorganization |
Severity levels
| major | Significant strategic shifts, large price changes, new product launches |
| moderate | Notable changes worth tracking: new features, messaging updates, minor pricing tweaks |
| minor | Small copy edits, typo fixes, cosmetic adjustments |
/api/v1/changes/:id
Get Change Detail
Returns the full detail of a specific change, including the AI-generated analysis, before/after snapshots, and A/B testing detection. This is the deepest endpoint in the competitor analysis API, providing everything you need to understand exactly what a competitor changed and what it might mean strategically.
Path parameters
| id | string, required | The change's public ID (e.g., chg_Xp4kLm8) |
Response
{
"data": {
"id": "chg_Xp4kLm8",
"competitor_id": "comp_8xKm2Nq",
"competitor_name": "Acme Corp",
"page_url": "https://www.acmecorp.com/pricing",
"page_type": "pricing",
"change_type": "pricing",
"severity": "major",
"summary": "Enterprise tier price increased from $299/mo to $349/mo. New 'Scale' tier added at $199/mo.",
"detected_at": "2026-03-22T14:33:00Z",
"reviewed": false,
"bookmarked": false,
"ai_analysis": {
"what_changed": "Acme Corp restructured their pricing page with two significant modifications. The Enterprise tier saw a 16.7% price increase from $299/month to $349/month. Simultaneously, they introduced a new 'Scale' tier positioned between their existing Pro ($99/mo) and Enterprise offerings at $199/month.",
"why_it_matters": "This pricing restructure signals that Acme Corp is moving upmarket. The new Scale tier creates a smoother upgrade path, potentially reducing churn at the Pro level while extracting more revenue from mid-market customers. The Enterprise price increase suggests strong demand at that level and confidence in their enterprise value proposition.",
"recommended_action": "Review your own mid-market pricing. If you do not have a comparable tier between $150-$250/month, you may lose deals to Acme's new Scale plan. Consider whether your Enterprise pricing should also be adjusted. Brief the sales team on this change before upcoming deals against Acme.",
"competitive_impact": "high"
},
"ab_test_detected": false,
"snapshots": {
"before": {
"captured_at": "2026-03-20T06:00:00Z",
"content_hash": "a1b2c3d4e5f6..."
},
"after": {
"captured_at": "2026-03-22T14:30:00Z",
"content_hash": "f6e5d4c3b2a1..."
}
}
}
}
About A/B testing detection: When RivalCheck detects that a page is alternating between different versions (e.g., the pricing page shows different prices on different visits), the ab_test_detected field is set to true. This is crucial for the pricing change detection API use case, as it prevents false positives from being treated as permanent changes.
/api/v1/competitors/:id/battle_card
Get Battle Card
Retrieve the AI-generated battle card for a competitor. Battle cards are a cornerstone of competitive sales enablement, and the battle card API lets you embed them directly into your CRM, sales playbooks, or AI-assisted deal preparation workflows. Cards are generated from the latest monitoring data and include strengths, weaknesses, pricing comparisons, objection handling scripts, and elevator pitches.
Path parameters
| id | string, required | The competitor's public ID |
Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
| format_type | string | full |
full returns all sections in a single structured JSON object.
markdown returns the entire card as a formatted Markdown string (ideal for Slack, Notion, or AI agents).
structured returns sections as an array with section keys and content.
|
Response (format_type=full)
{
"data": {
"id": "bc_Vm3xKp7",
"competitor_id": "comp_8xKm2Nq",
"competitor_name": "Acme Corp",
"generated_at": "2026-03-20T12:00:00Z",
"stale": false,
"sections": {
"overview": "Acme Corp is a mid-market B2B SaaS platform focused on project management and team collaboration. Founded in 2019, they have raised $45M in Series B funding and serve approximately 2,000 customers. They position themselves as the 'all-in-one workspace' for growing teams, competing primarily on breadth of features rather than depth in any single area.",
"strengths": [
"Strong brand recognition in the 50-200 employee segment",
"Comprehensive feature set spanning project management, docs, and chat",
"Aggressive content marketing with high-ranking SEO pages",
"Recently added AI features that are getting positive early reviews",
"Free tier available, making bottom-up adoption easy"
],
"weaknesses": [
"Enterprise tier pricing recently increased 16.7%, causing customer complaints on social media",
"No native integrations with industry-specific tools (e.g., Figma, GitHub)",
"Mobile app has 3.2-star rating on App Store with complaints about performance",
"No SOC 2 Type II certification yet (in progress per their security page)",
"Customer support response times averaging 24+ hours based on review sites"
],
"pricing_comparison": {
"their_plans": [
{"name": "Free", "price": "$0/mo", "notes": "Up to 5 users, limited features"},
{"name": "Pro", "price": "$99/mo", "notes": "Up to 25 users, all core features"},
{"name": "Scale", "price": "$199/mo", "notes": "NEW - Up to 100 users, advanced analytics"},
{"name": "Enterprise", "price": "$349/mo", "notes": "Unlimited users, SSO, priority support"}
],
"key_differences": "Acme prices per-workspace while we price per-user. For teams of 10-30, Acme is typically cheaper. Above 30 users, our pricing becomes more competitive. Their new Scale tier directly targets the segment where we have historically won deals.",
"talk_track": "When a prospect mentions Acme's pricing, emphasize our per-user model's predictability and the fact that our Pro plan includes features they charge Enterprise prices for (SSO, API access, custom roles)."
},
"how_we_win": [
"Lead with our superior integration ecosystem (200+ native integrations vs their 45)",
"Demonstrate our mobile experience side-by-side — our 4.7-star app vs their 3.2",
"Emphasize our SOC 2 Type II and GDPR compliance for security-conscious buyers",
"For larger teams (30+), show the TCO comparison where our per-user pricing wins",
"Highlight our 4-hour average support response time with customer testimonials"
],
"objection_handling": [
{
"objection": "Acme has a free tier and you don't.",
"response": "That's true — Acme's free tier is designed to get teams started, but it's limited to 5 users with no integrations or reporting. Our 14-day trial gives you full access to everything, so you can make a real evaluation. Most teams that try both choose us because they see the depth difference immediately."
},
{
"objection": "Acme just launched AI features.",
"response": "We've had AI-powered insights for over a year now. Acme's AI is a first-generation addition. Ask to see a side-by-side comparison of the AI outputs — ours are more actionable because they're trained on deeper data integrations. We're happy to do a proof-of-concept."
},
{
"objection": "Acme seems more established.",
"response": "Acme has strong brand awareness, but look at the trajectory. We've grown 3x year-over-year and have a higher NPS score (72 vs their 54). More importantly, look at which direction each product is heading. Their recent pricing increases and feature additions are playing catch-up in areas where we've led for years."
}
],
"elevator_pitch": "While Acme Corp offers a broad but shallow all-in-one workspace, we provide deeper functionality where it matters most — with 200+ integrations, enterprise-grade security, award-winning mobile experience, and AI that's been battle-tested for over a year. Teams that evaluate both choose us 68% of the time because of the depth difference."
}
}
}
Battle card sections
| Section | Description |
|---|---|
| overview | Company background, positioning, market segment, and recent trajectory |
| strengths | Array of the competitor's key advantages and differentiators |
| weaknesses | Array of known weaknesses, gaps, and vulnerabilities |
| pricing_comparison | Detailed pricing breakdown with plans, key differences, and sales talk tracks |
| how_we_win | Array of specific strategies and tactics for winning deals against this competitor |
| objection_handling | Array of common objections with recommended responses |
| elevator_pitch | A concise summary positioning you against this specific competitor |
Staleness: The stale field is true when significant changes have been detected since the battle card was last generated. Use the generate endpoint to refresh it. See our guide on building with the battle cards API for best practices.
/api/v1/competitors/:id/battle_card/generate
Generate or Regenerate Battle Card
Trigger the (re)generation of a battle card for the specified competitor. This is an asynchronous operation: the endpoint returns immediately with a 202 Accepted status. Generation typically takes 15-30 seconds. Poll the GET battle_card endpoint to check for completion, or listen for the battle_card.updated webhook event.
Path parameters
| id | string, required | The competitor's public ID |
Request example
curl -X POST https://app.rivalcheck.com/api/v1/competitors/comp_8xKm2Nq/battle_card/generate \ -H "Authorization: Bearer rc_live_YOUR_KEY"
Response (202 Accepted)
{
"message": "Battle card generation started.",
"competitor_id": "comp_8xKm2Nq",
"estimated_seconds": 20,
"poll_url": "/api/v1/competitors/comp_8xKm2Nq/battle_card"
}
Polling pattern: After triggering generation, wait 5 seconds, then poll the GET endpoint every 5 seconds until generated_at is more recent than your trigger time. Or, simply use a webhook for a push-based approach.
/api/v1/landscape
Competitive Landscape Summary
Returns a high-level overview of your entire competitive landscape: all competitors with their activity metrics, severity breakdowns, change type distributions, and the latest pricing intelligence. This endpoint powers executive dashboards and weekly competitive briefings. It is one of the most valuable endpoints in the competitive intelligence API for teams that need a bird's-eye view.
Response
{
"data": {
"total_competitors": 5,
"total_changes_30d": 34,
"severity_breakdown": {
"major": 4,
"moderate": 12,
"minor": 18
},
"type_breakdown": {
"pricing": 6,
"content": 19,
"layout": 9
},
"competitors": [
{
"id": "comp_8xKm2Nq",
"name": "Acme Corp",
"status": "active",
"changes_30d": 12,
"last_change_at": "2026-03-22T14:33:00Z",
"severity_breakdown": {"major": 2, "moderate": 5, "minor": 5},
"type_breakdown": {"pricing": 3, "content": 6, "layout": 3},
"latest_pricing_change": {
"id": "chg_Xp4kLm8",
"summary": "Enterprise tier price increased from $299/mo to $349/mo. New 'Scale' tier added at $199/mo.",
"detected_at": "2026-03-22T14:33:00Z",
"severity": "major"
}
},
{
"id": "comp_3pRtYvW",
"name": "BetaRival",
"status": "active",
"changes_30d": 8,
"last_change_at": "2026-03-19T10:05:00Z",
"severity_breakdown": {"major": 1, "moderate": 3, "minor": 4},
"type_breakdown": {"pricing": 1, "content": 5, "layout": 2},
"latest_pricing_change": {
"id": "chg_Bm2wQt7",
"summary": "Free tier removed. Lowest plan now $29/mo.",
"detected_at": "2026-03-19T10:05:00Z",
"severity": "major"
}
},
{
"id": "comp_Zt6mHg3",
"name": "Gamma Solutions",
"status": "active",
"changes_30d": 14,
"last_change_at": "2026-03-23T08:12:00Z",
"severity_breakdown": {"major": 1, "moderate": 4, "minor": 9},
"type_breakdown": {"pricing": 2, "content": 8, "layout": 4},
"latest_pricing_change": null
}
],
"generated_at": "2026-03-24T10:00:00Z"
}
}
/api/v1/account
Account Information
Returns your current plan details, usage statistics, and feature limits. Useful for building usage dashboards, enforcing client-side limits, or checking whether you can add more competitors before making a POST request.
Response
{
"data": {
"organisation": {
"id": "org_Qm4xNr8",
"name": "My Company Inc"
},
"plan": {
"name": "Growth",
"interval": "monthly",
"price_cents": 4900,
"currency": "usd"
},
"usage": {
"competitors_used": 8,
"competitors_limit": 15,
"pages_used": 32,
"pages_limit": 75,
"api_requests_today": 153,
"api_requests_limit": 1000
},
"features": {
"battle_cards": true,
"webhooks": true,
"mcp_access": true,
"api_access": true,
"email_digests": true,
"custom_pages": true
}
}
}
Code Examples
Complete, copy-paste-ready examples for the most common competitor tracking API operations in multiple languages.
Fetch Recent Pricing Changes
This is the most common use case for the pricing change detection API: retrieve all pricing changes from the past 7 days so your team can respond quickly.
curl
curl -G https://app.rivalcheck.com/api/v1/changes \ -H "Authorization: Bearer rc_live_YOUR_KEY" \ -d type=pricing \ -d since=2026-03-17T00:00:00Z \ -d limit=50
Python
import requests
from datetime import datetime, timedelta
api_key = "rc_live_YOUR_KEY"
seven_days_ago = (datetime.utcnow() - timedelta(days=7)).isoformat() + "Z"
response = requests.get(
"https://app.rivalcheck.com/api/v1/changes",
headers={"Authorization": f"Bearer {api_key}"},
params={
"type": "pricing",
"since": seven_days_ago,
"limit": 50,
},
)
response.raise_for_status()
data = response.json()
for change in data["data"]:
print(f"[{change['severity'].upper()}] {change['competitor_name']}")
print(f" {change['summary']}")
print(f" Detected: {change['detected_at']}")
print()
JavaScript (Node.js / fetch)
const API_KEY = process.env.RIVALCHECK_API_KEY;
const sevenDaysAgo = new Date(Date.now() - 7 * 86400000).toISOString();
const params = new URLSearchParams({
type: "pricing",
since: sevenDaysAgo,
limit: "50",
});
const response = await fetch(
`https://app.rivalcheck.com/api/v1/changes?${params}`,
{
headers: { Authorization: `Bearer ${API_KEY}` },
}
);
if (!response.ok) {
const err = await response.json();
throw new Error(`API error: ${err.error.message}`);
}
const { data, meta } = await response.json();
console.log(`Found ${meta.total} pricing changes in the last 7 days:\n`);
for (const change of data) {
console.log(`[${change.severity.toUpperCase()}] ${change.competitor_name}`);
console.log(` ${change.summary}`);
console.log(` Detected: ${change.detected_at}\n`);
}
Ruby
require "net/http"
require "json"
require "uri"
api_key = ENV.fetch("RIVALCHECK_API_KEY")
since = (Time.now.utc - 7 * 86_400).iso8601
uri = URI("https://app.rivalcheck.com/api/v1/changes")
uri.query = URI.encode_www_form(type: "pricing", since: since, limit: 50)
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{api_key}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
data = JSON.parse(response.body)
data["data"].each do |change|
puts "[#{change['severity'].upcase}] #{change['competitor_name']}"
puts " #{change['summary']}"
puts " Detected: #{change['detected_at']}"
puts
end
Fetch a Battle Card for Sales Prep
Retrieve a battle card in markdown format, ready to paste into Slack, Notion, or any other tool your sales team uses. The battle card API supports multiple output formats for exactly this purpose.
curl
curl -G https://app.rivalcheck.com/api/v1/competitors/comp_8xKm2Nq/battle_card \ -H "Authorization: Bearer rc_live_YOUR_KEY" \ -d format_type=markdown
Python
import requests
api_key = "rc_live_YOUR_KEY"
competitor_id = "comp_8xKm2Nq"
response = requests.get(
f"https://app.rivalcheck.com/api/v1/competitors/{competitor_id}/battle_card",
headers={"Authorization": f"Bearer {api_key}"},
params={"format_type": "markdown"},
)
response.raise_for_status()
card = response.json()["data"]
# Check if the card is stale and needs regeneration
if card["stale"]:
print("Warning: Battle card is stale. Consider regenerating.")
regen = requests.post(
f"https://app.rivalcheck.com/api/v1/competitors/{competitor_id}/battle_card/generate",
headers={"Authorization": f"Bearer {api_key}"},
)
print(f"Regeneration triggered: {regen.json()['message']}")
print(card["markdown"])
JavaScript
const API_KEY = process.env.RIVALCHECK_API_KEY;
const competitorId = "comp_8xKm2Nq";
const params = new URLSearchParams({ format_type: "markdown" });
const response = await fetch(
`https://app.rivalcheck.com/api/v1/competitors/${competitorId}/battle_card?${params}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
const { data: card } = await response.json();
if (card.stale) {
console.warn("Battle card is stale. Triggering regeneration...");
await fetch(
`https://app.rivalcheck.com/api/v1/competitors/${competitorId}/battle_card/generate`,
{ method: "POST", headers: { Authorization: `Bearer ${API_KEY}` } }
);
}
console.log(card.markdown);
Ruby
require "net/http"
require "json"
api_key = ENV.fetch("RIVALCHECK_API_KEY")
competitor_id = "comp_8xKm2Nq"
uri = URI("https://app.rivalcheck.com/api/v1/competitors/#{competitor_id}/battle_card")
uri.query = URI.encode_www_form(format_type: "markdown")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{api_key}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
card = JSON.parse(response.body)["data"]
puts card["stale"] ? "Warning: card is stale" : "Card is fresh"
puts card["markdown"]
Add a Competitor and Wait for Discovery
Programmatically add a new competitor and poll until discovery is complete. This pattern is useful for onboarding flows or bulk competitor imports.
Python
import requests
import time
api_key = "rc_live_YOUR_KEY"
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
# Step 1: Add the competitor
create_resp = requests.post(
"https://app.rivalcheck.com/api/v1/competitors",
headers=headers,
json={"website_url": "https://www.newrival.com", "name": "NewRival"},
)
create_resp.raise_for_status()
competitor = create_resp.json()["data"]
comp_id = competitor["id"]
print(f"Created competitor: {comp_id} (status: {competitor['status']})")
# Step 2: Poll until active
max_attempts = 30
for attempt in range(max_attempts):
time.sleep(10) # Check every 10 seconds
detail_resp = requests.get(
f"https://app.rivalcheck.com/api/v1/competitors/{comp_id}",
headers=headers,
)
status = detail_resp.json()["data"]["status"]
print(f" Attempt {attempt + 1}: status = {status}")
if status == "active":
pages = detail_resp.json()["data"]["pages"]
print(f"Discovery complete! Monitoring {len(pages)} pages.")
break
elif status == "error":
print("Discovery failed. Check the website URL.")
break
else:
print("Timed out waiting for discovery.")
JavaScript
const API_KEY = process.env.RIVALCHECK_API_KEY;
const headers = {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
};
// Step 1: Add the competitor
const createResp = await fetch("https://app.rivalcheck.com/api/v1/competitors", {
method: "POST",
headers,
body: JSON.stringify({
website_url: "https://www.newrival.com",
name: "NewRival",
}),
});
const { data: competitor } = await createResp.json();
console.log(`Created: ${competitor.id} (${competitor.status})`);
// Step 2: Poll until active
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
for (let attempt = 0; attempt < 30; attempt++) {
await sleep(10_000);
const resp = await fetch(
`https://app.rivalcheck.com/api/v1/competitors/${competitor.id}`,
{ headers }
);
const { data } = await resp.json();
console.log(` Attempt ${attempt + 1}: ${data.status}`);
if (data.status === "active") {
console.log(`Discovery complete! Monitoring ${data.pages.length} pages.`);
break;
}
if (data.status === "error") {
console.error("Discovery failed.");
break;
}
}
Real-World Scenarios
Practical patterns showing how teams use the competitor monitoring API in production.
Automated Pricing Alert Pipeline
A SaaS company runs a cron job every morning that calls GET /api/v1/changes?type=pricing&since=<yesterday>&severity=major. If results are returned, it posts a formatted message to the #competitive-intel Slack channel, tags the VP of Product, and creates a task in Linear. The pricing change detection API ensures no pricing move goes unnoticed.
Endpoints used: GET /changes
AI-Powered Sales Call Prep
Before every sales call, an AI agent (via MCP or API) fetches the battle card for the deal's primary competitor and the last 30 days of changes. It generates a custom briefing document with talking points, objection responses, and a pricing comparison table. The sales rep receives this in their inbox 30 minutes before the call. The battle card API and competitor analysis API work together here.
Endpoints used: GET /competitors/:id/battle_card, GET /competitors/:id/changes
Weekly Board-Ready Competitive Report
Every Monday, a scheduled script calls GET /api/v1/landscape and GET /api/v1/changes?since=<7_days_ago>, then feeds the results to an LLM with a prompt template to generate an executive-ready competitive briefing as a PDF. The report covers competitor activity trends, notable moves, and strategic implications.
Endpoints used: GET /landscape, GET /changes
CRM Integration for Deal Intelligence
A Salesforce integration uses webhooks to receive change.detected events in real time. When a pricing change is detected for a competitor involved in an active deal, the integration automatically adds a note to the opportunity in Salesforce and alerts the deal owner. Battle cards are synced nightly to custom Salesforce objects using the competitor tracking API.
Endpoints used: Webhooks, GET /competitors, GET /competitors/:id/battle_card
Bulk Competitor Onboarding
A competitive intelligence team joining RivalCheck uses a script to add 15 competitors via POST /api/v1/competitors in sequence, with a 5-second delay between each. They then monitor the GET /api/v1/account endpoint to track usage against their plan limits. After all competitors reach active status, they trigger battle card generation for each one.
Endpoints used: POST /competitors, GET /account, POST /competitors/:id/battle_card/generate
Start Building with the Competitive Intelligence API
Create a free account, generate your API key, and make your first request in under two minutes. All plans include full API access.
Need help? Reach us at support@rivalcheck.com