Overview
You get a competitor-intel report as JSON from one call by having your agent fan out to Scavio's Google, Reddit, and YouTube endpoints and merge the results into one object. Each datapoint carries a source URL and a captured_at timestamp, so the agent can cite where a number came from and how fresh it is. Call it from Scavio's hosted MCP server inside Claude or Cursor, or run the same flow as a plain REST script behind a cron job. Raw follower or star counts are commodity; the part that holds up is provenance and freshness.
Trigger
On-demand agent tool call, or daily cron
Schedule
On-demand / daily
Workflow Steps
Name the competitor and the surfaces
Pick the competitor and decide which surfaces matter. This workflow reads three: Google search positions, Reddit mentions, and YouTube presence. Scavio covers those plus TikTok, Amazon, and Walmart, so add or drop surfaces to fit what you actually track. Pass the competitor name as one input to all three calls. Keep the list short on purpose. Three sources you can cite beat ten you cannot, and a tight report is cheaper to refresh on a schedule.
Pull Google SERP positions
POST to /api/v1/google with {"query": competitor, "light_request": false}. The full request returns organic results, knowledge_graph, questions, and related_searches. Keep the rank and the link for each result, because the link is the provenance for that rank. Full Google requests cost 2 credits; a light request costs 1 but returns less. Scavio does not return AI Overviews, so the organic list is what you cite for position.
Pull Reddit mentions
POST to /api/v1/reddit/search with {"query": competitor, "sort": "new"}. Sorting by new surfaces the freshest community chatter, which is the point when you care about what people are saying this week. You get threads and comments with their scores, plus the permalink that lets a reader verify the quote. This call costs 2 credits.
Pull YouTube presence
POST to /api/v1/youtube/search with the body param search set to the competitor name. Note that YouTube uses search, not query, in the wire body, so do not copy the Google body shape here. You get the videos, channels, and view counts, each with a watch link. This call costs 1 credit.
Stamp every datapoint with provenance
As you flatten each source, attach a source_url and a captured_at timestamp to every row. The timestamp comes from the runtime, datetime.now in Python or new Date in Node, not a hardcoded value, so the report tells the truth about when it was captured. This is the step that turns commodity numbers into something an agent can cite and trust.
Merge into one report object
Combine the three source blocks under a single object with the competitor name and a top-level generated_at. The Node version runs the three calls in parallel with Promise.all; the Python version runs them in sequence, which is simpler to read and fine for a daily job. Return the whole thing as JSON so the agent gets one structured payload, not three loose responses.
Wire it to an agent or a cron
From an MCP client, point at https://mcp.scavio.dev/mcp with the x-api-key header and let the agent call the tools on demand. For an unattended refresh, run the REST script on a daily cron or in n8n. Scavio is a data layer and does not schedule anything itself, so the cron or the agent owns the timing.
Python Implementation
"""
Build a one-call competitor-intel report as structured JSON.
Combines Google SERP positions + Reddit mentions + YouTube presence.
Every datapoint carries a source url and a captured_at timestamp,
because raw counts are commodity; provenance and freshness are the value.
Requires: pip install requests
Set SCAVIO_API_KEY in your environment.
"""
import os
import json
from datetime import datetime, timezone
import requests
API_KEY = os.environ["SCAVIO_API_KEY"]
BASE = "https://api.scavio.dev/api/v1"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
COMPETITOR = "Acme Analytics"
def now_iso():
return datetime.now(timezone.utc).isoformat()
def post(path, body):
resp = requests.post(f"{BASE}{path}", headers=HEADERS, json=body, timeout=60)
resp.raise_for_status()
return resp.json()
def google_positions(competitor):
data = post("/google", {"query": competitor, "light_request": False})
captured_at = now_iso()
rows = []
for i, item in enumerate(data.get("organic", []), start=1):
rows.append({
"position": item.get("position", i),
"title": item.get("title"),
"source_url": item.get("link"),
"captured_at": captured_at,
})
kg = data.get("knowledge_graph") or {}
return {
"organic": rows,
"knowledge_graph": kg or None,
"questions": data.get("questions", []),
"related_searches": data.get("related_searches", []),
"captured_at": captured_at,
}
def reddit_mentions(competitor):
data = post("/reddit/search", {"query": competitor, "sort": "new"})
captured_at = now_iso()
threads = []
for t in data.get("threads", []):
threads.append({
"title": t.get("title"),
"score": t.get("score"),
"subreddit": t.get("subreddit"),
"source_url": t.get("url") or t.get("permalink"),
"captured_at": captured_at,
})
return {"threads": threads, "captured_at": captured_at}
def youtube_presence(competitor):
data = post("/youtube/search", {"search": competitor})
captured_at = now_iso()
videos = []
for v in data.get("videos", []):
videos.append({
"title": v.get("title"),
"channel": v.get("channel"),
"views": v.get("views"),
"source_url": v.get("link") or v.get("url"),
"captured_at": captured_at,
})
return {"videos": videos, "captured_at": captured_at}
def build_report(competitor):
return {
"competitor": competitor,
"generated_at": now_iso(),
"sources": {
"google": google_positions(competitor),
"reddit": reddit_mentions(competitor),
"youtube": youtube_presence(competitor),
},
}
if __name__ == "__main__":
report = build_report(COMPETITOR)
print(json.dumps(report, indent=2, ensure_ascii=False))
JavaScript Implementation
/**
* Build a one-call competitor-intel report as structured JSON.
* Combines Google SERP positions + Reddit mentions + YouTube presence.
* Every datapoint carries a source url and a captured_at timestamp,
* because raw counts are commodity; provenance and freshness are the value.
*
* Node 18+ (built-in fetch). Set SCAVIO_API_KEY in your environment.
*/
const API_KEY = process.env.SCAVIO_API_KEY;
const BASE = "https://api.scavio.dev/api/v1";
const HEADERS = {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
};
const COMPETITOR = "Acme Analytics";
const nowIso = () => new Date().toISOString();
async function post(path, body) {
const resp = await fetch(`${BASE}${path}`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify(body),
});
if (!resp.ok) throw new Error(`${resp.status} ${await resp.text()}`);
return resp.json();
}
async function googlePositions(competitor) {
const data = await post("/google", { query: competitor, light_request: false });
const capturedAt = nowIso();
const organic = (data.organic || []).map((item, i) => ({
position: item.position ?? i + 1,
title: item.title,
source_url: item.link,
captured_at: capturedAt,
}));
return {
organic,
knowledge_graph: data.knowledge_graph || null,
questions: data.questions || [],
related_searches: data.related_searches || [],
captured_at: capturedAt,
};
}
async function redditMentions(competitor) {
const data = await post("/reddit/search", { query: competitor, sort: "new" });
const capturedAt = nowIso();
const threads = (data.threads || []).map((t) => ({
title: t.title,
score: t.score,
subreddit: t.subreddit,
source_url: t.url || t.permalink,
captured_at: capturedAt,
}));
return { threads, captured_at: capturedAt };
}
async function youtubePresence(competitor) {
const data = await post("/youtube/search", { search: competitor });
const capturedAt = nowIso();
const videos = (data.videos || []).map((v) => ({
title: v.title,
channel: v.channel,
views: v.views,
source_url: v.link || v.url,
captured_at: capturedAt,
}));
return { videos, captured_at: capturedAt };
}
async function buildReport(competitor) {
const [google, reddit, youtube] = await Promise.all([
googlePositions(competitor),
redditMentions(competitor),
youtubePresence(competitor),
]);
return {
competitor,
generated_at: nowIso(),
sources: { google, reddit, youtube },
};
}
buildReport(COMPETITOR)
.then((report) => console.log(JSON.stringify(report, null, 2)))
.catch((err) => {
console.error(err);
process.exit(1);
});
Platforms Used
Web search with knowledge graph, PAA, and AI overviews
Community, posts & threaded comments from any subreddit
YouTube
Video search with transcripts and metadata