API & MCP

Rival Ads exposes the same competitor-monitoring capabilities through a versioned REST API and a remote MCP server. Both are thin interfaces over the dashboard’s domain services, so plan limits, source validation, tenant isolation and report rules stay identical everywhere.

Access is fully self-serve: every plan starts with a 14-day free trial, and a workspace owner can create API keys in Settings → Developer without contacting anyone. Compatibility rules are published in API versioning & deprecation.

Choose a connection

  • Use the REST API for scripts, data pipelines, dashboards and backend integrations. It accepts workspace-scoped API keys.
  • Use MCP with OAuth 2.1 and PKCE for interactive AI clients. The client opens Rival Ads, the user signs in, reviews the requested read or write permissions and approves the connection.
  • Use MCP with an API key for headless agents, CI and server-to-server automations that cannot complete an interactive sign-in.

The production REST base URL is https://www.rivalads.io/api/v1. The remote MCP endpoint is https://www.rivalads.io/api/mcp.

Create an API key

Only the workspace owner can manage developer credentials.

  1. Open Settings → Developer.
  2. Enter a descriptive name such as Weekly client report.
  3. Choose Read only or Read and write.
  4. Choose an expiry and select Create API key.
  5. Copy the ra_live_… value immediately. Rival Ads stores only a hash and cannot show it again.

Send the key as a Bearer token:

curl https://www.rivalads.io/api/v1/monitors \
  -H "Authorization: Bearer ra_live_your_key"

The x-api-key header is also accepted. Prefer Authorization: Bearer because it works for both REST and MCP. Never put a key in a URL, browser bundle or repository. Revoke a leaked or unused key from Settings → Developer.

REST API resources

The API covers the workspace, monitors, projects, ad movement, stored strategy reads, sync jobs, swipe files, public report links and the stored research resources below.

  • GET /workspace
  • GET|POST /monitors
  • GET|PATCH|DELETE /monitors/{monitorId}
  • GET /monitors/{monitorId}/ads
  • GET /monitors/{monitorId}/analyses
  • POST|GET /monitors/{monitorId}/sync
  • GET|POST /projects
  • GET|PATCH|DELETE /projects/{projectId}
  • GET|POST /library/folders
  • PATCH|DELETE /library/folders/{folderId}
  • GET /library/ads
  • PUT|DELETE /library/ads/{adId}
  • GET|PATCH /monitors/{monitorId}/report-share

List endpoints use cursor pagination. Pass limit from 1 to 100 and then send the returned pagination.nextCursor as cursor.

Every success response wraps the result in data. Errors use a stable shape:

{
  "error": {
    "code": "not_found",
    "message": "Monitor not found"
  }
}

The interactive, branded API reference is generated from the same Zod request contracts the routes validate. The raw OpenAPI 3.1 document is at /api/openapi.json.

Ad copy in the API

Ads carry the advertiser's own copy in bodyText, and the creative intelligence read alongside it: hook, angle, persona, cta, visualStyle, language, plus ocrText and transcript.

ocrText matters most for Google. The Ads Transparency Center publishes search ads as a rendered picture rather than as text, so bodyText is empty on every Google ad and the headline and description are in ocrText, read off the creative. transcript carries speech from video creatives.

Both are null until the ad's one-off intelligence read completes, which status reports as READY, PENDING or FAILED.

Stored research: search, discovery and landing pages

All of these resources need read access only. They query evidence Rival Ads already holds. They never call an LLM, transcribe a video, start a scrape, capture a page or enqueue background work. The AI client you connect pays for its own model's reasoning and answer. Rival Ads serves the stored data.

REST resourceMCP toolWhat you receive
GET /ads/searchsearch_adsMatching ads across a workspace, project or monitor, with field-match evidence, snippets, total matches and a cursor
GET /ads/{adId}get_adOne stored ad, including transcript, OCR, source dates, published reach and its landing-page reference
GET /inspiration/adssearch_inspirationA filtered page of canonical shared ads
GET /inspiration/ads/{channel}/{archiveId}get_inspiration_adA shared ad with its stored transcript and on-screen text
GET /inspiration/insightsget_inspiration_insightsDeduplicated creative mixes and launch counts; detail=all also returns bounded hooks, words, advertisers, launch weeks, video lengths and hook openers
GET /inspiration/risinglist_rising_advertisersRanked advertiser activity, source identities, launch/survival counts and the effective market/channel scope
GET /inspiration/rising/adsget_rising_advertiser_adsUp to 24 source-dated launches supporting an advertiser's ranking
GET /landing-pageslist_landing_pagesStored destinations, prices, capture dates, capture status, referring-ad counts and offer history
GET /landing-pages/{landingPageId}get_landing_pageOne landing page and its confirmed/unconfirmed price observations
GET /landing-pages/{landingPageId}/screenshotget_landing_page_screenshotCurrent image bytes, or a capture of record selected by observation
GET /inspiration/ads/{channel}/{archiveId}/assetget_inspiration_imageStored creative bytes selected by `asset=media

These JSON resources return { "data": ... }. A research list's data object contains its named collection (ads, advertisers or landingPages) and nextCursor. Keep the same filters and pass nextCursor as cursor until it is null. Default page size is 25. Maximums are 100 for own-ad/landing research, 60 for Inspiration and 50 for Rising. Rising's supporting-ads response states its fixed limit: 24; it is an evidence sample rather than a complete export.

Search your monitored ads

The q parameter uses the dashboard's existing keyword syntax: words match across ad copy, hooks, transcripts, OCR and creative intelligence. Quotes require a phrase, and -word excludes a term. It is lexical search; it does not buy embeddings or a generated answer.

curl -G https://www.rivalads.io/api/v1/ads/search \
  -H "Authorization: Bearer ra_live_your_key" \
  --data-urlencode 'q="free shipping" -sale' \
  --data-urlencode 'channel=META' \
  --data-urlencode 'limit=25'

Optional filters include projectId, monitorId, channel, format, angle, style, language, active=true|false and minDays=7|15|30|90|180|365. Project and monitor IDs must belong to the connected workspace. Search results say which fields matched. Fetch get_ad when you want the complete stored transcript or OCR rather than a snippet. The result's daysRunning uses Google's observed first-to-last-shown span for Google and a known delivery window for other channels; an unknown span stays null.

Browse shared research

An owner must first opt the workspace into Inspiration in the dashboard. Connecting a tool never opts you in automatically. Feed/detail/assets/insights return 403 outside the pool. Rising routes return 404 outside it. Other workspaces' opt-outs take effect on subsequent reads.

Inspiration supports the creative filters above, excluding project/monitor IDs, plus sort=newest|longest. Longest-running results are live, source-dated ads. Pool records expose the public advertiser, ad content and opaque asset URLs, never another workspace's monitor, project, private labels or storage paths.

Rising accepts window=14|30, comma-separated channels and markets, cursor and limit. Omitted channels/markets follow the workspace's monitored scope. Use all explicitly to widen it. Pass the row's channel, advertiserKey as advertiser, the same window, and any selected markets to the supporting-ads resource. Supporting ads also default to the workspace's monitored markets when markets is omitted.

The ranking is launches × (1 + seven-day survival), with source-dated launches only. These figures describe observable activity and longevity. They are not spend, revenue, conversions or proof of profitability.

Read offers and images

Landing-page lists accept projectId, monitorId, q (URL/title/description), captured=true|false, limit and cursor. Each price is dated. A history entry with confirmedAt: null is unconfirmed; only the canonical offer.signal and confirmed timeline establish a reportable price change. The first price-shaped text on a page can be a shipping threshold or old price, so use its screenshot for context.

Image and video URLs in research responses require the same Bearer credential as the parent request; they are not public or signed bearer links. MCP screenshot/image tools return image content directly, so your connected model can inspect the captured evidence. MCP images are capped at 5 MB. Use the authenticated REST resource for larger images or video. A missing capture returns 404 and never triggers a new capture.

Example AI requests:

  • “Find which monitored competitors mention free shipping in their videos.”
  • “Show long-running testimonial ads in our Inspiration pool.”
  • “Which advertisers launched the most new Meta ads in our markets?”
  • “Show this competitor's dated offer history and the screenshot behind its latest confirmed change.”

Connect an AI client with OAuth

Give a compatible MCP client only this server URL:

https://www.rivalads.io/api/mcp

The client discovers Rival Ads’ OAuth metadata, registers itself, uses an authorization code with PKCE and opens the consent screen. The available scopes are:

  • mcp:read — list workspaces and read monitors, projects, ad movement, stored research, analyses, library items, report-link state and sync state.
  • mcp:write — create, update or delete monitors, projects and library folders; save ads; request syncs; update report links.

OAuth connections are approved by a workspace owner and can access workspaces that person owns. If that account owns more than one workspace, tools require organizationId; call list_workspaces first. Revoke a client from Settings → Developer → OAuth connections.

Connect a headless MCP client

For a server or CI job, configure the same MCP URL with a Bearer API key:

{
  "mcpServers": {
    "rival-ads": {
      "url": "https://www.rivalads.io/api/mcp",
      "headers": {
        "Authorization": "Bearer ra_live_your_key"
      }
    }
  }
}

An API key is fixed to the workspace where it was created. A read-only key cannot call write tools. Use a short expiry and the narrowest access that works.

MCP tool groups

The server exposes small, task-oriented tools for:

  • listing available workspaces;
  • listing, reading, creating, editing and deleting monitors;
  • listing, creating, editing and deleting projects;
  • reading started, stopped and continuing ads;
  • reading stored strategy analyses without triggering a new model run;
  • searching monitored ads and retrieving complete stored ad evidence;
  • browsing the opted-in Inspiration pool, aggregates and Rising advertisers;
  • reading landing-page price histories and captured images;
  • listing and managing swipe-file folders and saved ads;
  • requesting and polling monitor sync jobs;
  • reading and updating revocable public report links.

Tool responses include structured JSON, and destructive tools are marked as destructive in their MCP annotations.

Security and tenant boundaries

API keys are attached to exactly one workspace. OAuth requests re-check the signed-in user’s current owner memberships. Every resource lookup also filters by that resolved workspace, so knowing another tenant’s ID does not grant access. Keys and OAuth connections have independent read/write permissions, expiry and revocation.

Sync requests enqueue work and return a job ID; poll the corresponding sync endpoint or MCP tool rather than holding the request open.

Rate limits

Each API key can make a set number of requests per minute, and the number grows with your plan. REST calls and MCP tool calls made with the same key share it. Bigger plans get more because an AI client working across more competitors makes more calls per task.

PlanRequests per minute, per API key
Starter600
Growth / AppSumo Tier 1600
Scale / AppSumo Tier 21,200
Agency / AppSumo Tier 31,800
Max / AppSumo Tier 42,400
Ultra / AppSumo Tier 53,000

The count resets at the start of every minute. A request over the limit gets a 429 response with code rate_limit_exceeded and a Retry-After header giving the seconds until the next minute; MCP clients receive JSON-RPC error -32029 with the same header. Rejected requests are not counted. When you upgrade, the higher limit applies from your next request, with no need to create a new key.

Next steps

Pinterest monitors and source details

Create with channel: "PINTEREST", pinterestAdvertiser: "Amazon.fr", regions: ["FR"] and a name. The advertiser value must match Pinterest's repository identity: Rival Ads checks it with Pinterest before creating or replacing the source and stores the exact name Pinterest returns. A name the repository does not list returns 409 with a pinterestAdvertiser field error, and a temporarily busy repository returns 503; retry after a minute. Neither uses a monitor slot. Omitted locations default to France. Updates use pinterestAdvertiser; a different advertiser requires the same explicit clearHistory confirmation as other sources.

Stored-ad reads, monitor ad movements and saved library ads expose a nullable pinterest object with source targeting, first/last shown, unique-user reach bands and review reasons. REST and MCP return the same allowlisted facts, without raw source payloads or private workspace data. euReach and reachByCountry count unique users, not impressions or spend. Source dates aggregate countries. Public source reads and collection use no LLM; the usual scheduled enrichment and strategy reads follow the workspace plan.