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

3. Explore your data

Fetch the latest changes across all competitors, retrieve a battle card for sales prep, or check the competitive landscape. Every endpoint is documented in detail below. You can also connect via MCP for AI-native access, or configure webhooks for real-time push notifications.

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 Unauthorized immediately.
  • 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-Remaining proactively and throttle when it drops below a threshold (e.g., 50).
  • Implement exponential backoff when you receive a 429. Start with the Retry-After value, 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.

GET /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).
GET /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"
      }
    ]
  }
}
POST /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.

GET /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
  }
}
GET /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
GET /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.

GET /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.

POST /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.

GET /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"
  }
}
GET /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