Connect Overindex

Use the same 34 typed research tools in the web app, over MCP, from the CLI, or through REST. Start by creating a key on the API keys page.

Connect via MCPResearch runsCLIREST APITool reference

Connect via MCP

One URL and one API key. Nothing to install, no repository to clone, no database or provider credentials anywhere near your machine — the endpoint speaks MCP’s streamable-HTTP transport and serves all 34 tools.

1 · The endpoint

https://overindex.app/api/mcp
Authorization: Bearer ugc_your_key_here

Create the key on the API keys page. It scopes every call to your workspace; runs and briefs are visible to nobody else.

2 · Claude Code

claude mcp add --transport http overindex https://overindex.app/api/mcp \
  --header "Authorization: Bearer ugc_your_key_here"

Then ask Claude things like “research protein coffee UGC and give me five concepts I can shoot tomorrow.”

3 · Claude Desktop / Cursor / any client

{
  "mcpServers": {
    "overindex": {
      "type": "http",
      "url": "https://overindex.app/api/mcp",
      "headers": { "Authorization": "Bearer ugc_your_key_here" }
    }
  }
}

Clients that cannot speak HTTP transports can run the stdio fallback from the repository (apps/mcp); it proxies to this same endpoint with the same key.

4 · Verify

npx @modelcontextprotocol/inspector \
  --cli https://overindex.app/api/mcp \
  --transport http --header "Authorization: Bearer ugc_..." \
  --method tools/list

You should see 34 tools. Results come back as structuredContent validated against the published JSON Schema in docs/api/mcp-schemas.json, and long jobs stream notifications/progress while they run.

5 · Render the visual strategy

After get_run returns done:true:
render_content_strategy({ "runId": "run_01J…" })

ChatGPT and other MCP Apps hosts open the result as an inline visual artifact with cited poster or private-video previews, source links, formats and beat-by-beat filming instructions. Plain MCP and stdio clients receive the same complete structuredContent without needing the UI.

Research runs

A run discovers, watches and clusters ~40 short-form videos for a subject and persists a cited brief. It takes minutes, so the API is asynchronous end to end: start it, then poll or stream. Every poll also keeps the run moving, so a run you are watching cannot stall.

Start — answers in under a second

curl -X POST https://overindex.app/api/v1/runs \
  -H "Authorization: Bearer ugc_..." \
  -H "content-type: application/json" \
  -H "Idempotency-Key: my-run-1" \
  -d '{"subject": "protein coffee", "platforms": ["tiktok"]}'

# 202 Accepted
# {"ok":true,"runId":"run_01J…","status":"queued","etaSeconds":480,
#  "pollUrl":"…/api/v1/runs/run_01J…","eventsUrl":"…/events","briefUrl":"…/brief"}

Repeating the same Idempotency-Key returns the same runId and starts nothing — a retried request can never fork a second paid run.

Poll, or stream

curl -H "Authorization: Bearer ugc_..." \
  "https://overindex.app/api/v1/runs/run_01J…?include=skips"

# server-sent events, resumable
curl -N -H "Authorization: Bearer ugc_..." -H "Last-Event-ID: 42" \
  "https://overindex.app/api/v1/runs/run_01J…/events"

The stream closes its window every few seconds and tells you the id to resume from; reconnect with Last-Event-ID and you get every event after it, exactly once. Counters only ever go up — they are count(*) over the rows the run wrote.

Read the brief, or stop the run

curl -H "Authorization: Bearer ugc_..." \
  "https://overindex.app/api/v1/runs/run_01J…/brief?format=markdown"
curl -H "Authorization: Bearer ugc_..." \
  "https://overindex.app/api/v1/runs/run_01J…/brief?format=csv"   # the reference table

curl -X POST -H "Authorization: Bearer ugc_..." \
  "https://overindex.app/api/v1/runs/run_01J…/cancel"

Cancelling stops the run within one phase, refunds the unspent part of the reservation and leaves everything already gathered readable (?include=references).

CLI

Every tool is also a subcommand, generated from the same registry — useful for scripting and piping into jq. With UGCGPT_API_KEY set it proxies to the hosted API, so it needs no database and no provider keys.

git clone https://github.com/garrrikkotua/ugcgpt && cd ugcgpt
pnpm install
export UGCGPT_API_KEY=ugc_your_key_here      # the only variable you need

pnpm ugc run start --subject "protein coffee"   # follows the run and prints the result
pnpm ugc run brief --run-id run_01J… --format markdown
pnpm ugc search videos "sleep tracker app"
pnpm ugc account audit calai.app --platform instagram --limit 30
pnpm ugc corpus stats

Add --json for machine-readable output and --no-follow to get the 202 answer immediately. Errors print their machine code first, e.g. [insufficient_credits]. Set DATABASE_URL instead of a key to run everything locally against your own database.

REST API

curl -X POST https://overindex.app/api/v1/tools/search_videos \
  -H "Authorization: Bearer ugc_..." \
  -H "content-type: application/json" \
  -d '{"query": "sleep tracker app"}'

Responses are { "ok": true, "result": … }, or { "ok": false, "code": "…", "error": "…" } with a 4xx status. The code is machine-readable and comes from a closed set — unauthorized, invalid_api_key, invalid_input, run_not_found, insufficient_credits, rate_limited, provider_throttled and friends — so a client never has to match on prose.

Each key gets 300 units per rolling 24h; tools marked 10 units watch video with an LLM or sweep many API calls — everything else costs 1 unit. Exceeding the limit returns 429.

Tool reference

Tool names and arguments are identical across MCP, CLI, and REST.

POST /api/v1/tools/start_run10 units

Start a research run. Standard watches 40 videos for 1 credit; deep watches 80 for 2. Mini audits one public @handle (the user's own or a competitor) or workspace-owned uploads, watches at most 10 for 0.25 credit, and produces account coaching; public-handle ownership is not verified. Returns immediately unless wait:true.

CLI: ugc start run · ugc run start

Arguments for start_run
FieldTypeRequiredDescription
subjectstringrequiredWhat to research, e.g. "calorie tracking apps"
platformsarrayoptionalDefaults to both TikTok and Instagram Reels.
windowDaysnumberoptionalRecency window in days
depth"mini" | "standard" | "deep"optional
watchBudgetnumberoptionalVideos to watch
maxAccountFollowersnumberoptionalDemote videos from accounts bigger than this (default 500000): a huge audience explains the views, so they say little about what made the video work. Lower it for a small niche, e.g. 100000.
includeUploadsbooleanoptionalFor an account subject, also include this workspace's private uploads
idempotencyKeystringoptionalRepeat with the same key to get the same run instead of starting a second one
scopingAnswerstringoptionalAnswer to the scoping question an earlier ambiguous start_run returned. Changes the plan.
waitbooleanoptionalBlock until the run finishes. Defaults to true only on the CLI, where a human is watching a terminal; every remote door (REST, MCP, the agent) returns in <1s and keeps working in the background.
waitSecondsnumberdefault 600Inline driving budget
POST /api/v1/tools/research_step10 units

Advance a research run by one invocation (~200s of work) and return its compact status. Call repeatedly until it returns done:true — a full run is 2–3 calls, not one per phase. Safe to call concurrently: whoever holds the run lease does the work and everyone else returns the current status.

CLI: ugc research step · ugc run step

Arguments for research_step
FieldTypeRequiredDescription
runIdstringrequiredRun id, e.g. run_01J…
deadlineSecondsnumberdefault 200Wall-clock budget for this invocation
POST /api/v1/tools/get_run1 unit

Read a run: status, phase, per-stage counters, cost so far, and whether its lease is stale. Polling this is also what keeps a run moving — a poll that finds nobody driving kicks the run in the background before answering (it never blocks). Pass kick:false for a pure read.

CLI: ugc get run · ugc run get

Arguments for get_run
FieldTypeRequiredDescription
runIdstringrequiredRun id, e.g. run_01J…
kickbooleandefault trueKick a stalled run in the background before answering (driver B).
POST /api/v1/tools/get_brief1 unit

Fetch a finished run's brief. Defaults to a compact summary (counts, format labels, reference ids) that is safe to hold in an agent's context; ask for format "markdown", "json" or "csv" only when the full document is actually needed.

CLI: ugc get brief · ugc run brief

Arguments for get_brief
FieldTypeRequiredDescription
runIdstringrequiredRun id, e.g. run_01J…
format"summary" | "markdown" | "json" | "csv"default "summary"
POST /api/v1/tools/render_content_strategy1 unit

Render a completed research run as a visual content-strategy artifact: graph-confirmed promoter accounts when available, every cited video with its poster preview and link, winning formats with resolved median views, and complete filming instructions (hook, timed beats, shot list, sound, CTA and modeled-on references). Call after get_run reports done. In MCP Apps hosts such as ChatGPT it opens an inline visual document; in other clients it returns the same portable structured data.

CLI: ugc render content strategy · ugc run artifact

Arguments for render_content_strategy
FieldTypeRequiredDescription
runIdstringrequiredThe completed Overindex research run id
POST /api/v1/tools/cancel_run1 unit

Cancel a running research run. It stops within one phase boundary and stops watching immediately; work already persisted (analyses, references) stays readable, and the unspent part of the credit reservation is refunded.

CLI: ugc cancel run · ugc run cancel

Arguments for cancel_run
FieldTypeRequiredDescription
runIdstringrequiredRun id, e.g. run_01J…
POST /api/v1/tools/answer_scoping1 unit

Answer the scoping question a run returned at start. The answer is folded into the subject before the plan is built, so it genuinely changes the queries, hashtags and rubric the run uses. A run waits a short grace for this and then plans without it — answering late is a no-op, never a block.

CLI: ugc answer scoping · ugc run answer scoping

Arguments for answer_scoping
FieldTypeRequiredDescription
runIdstringrequiredRun id, e.g. run_01J…
answerstringrequiredThe caller's choice, in their own words
POST /api/v1/tools/crawl_step1 unit

Operator-only. Advance the scheduled niche crawler by one invocation: for one niche (or, with no niche, the least-recently crawled niches until the deadline), discover → select → watch through the run pipeline under the system org, metered by the crawler’s daily USD ceiling (CRAWLER_DAILY_USD_CEILING, default $5). Stops at the ceiling and records why; the next call resumes where it stopped. dryRun discovers and selects without watching. Refuses callers that are not the system org, the CLI/cron, or an operator.

CLI: ugc crawl step · ugc crawler step

Arguments for crawl_step
FieldTypeRequiredDescription
nichestringoptionalA niche slug (see corpus_niches). Omitted: sweep niches oldest-first until the deadline.
deadlineSecondsnumberdefault 200Wall-clock budget for this invocation
dryRunbooleandefault falseDiscover and select, report what would be watched, spend nothing on watching
maxNichesnumberoptionalWhen sweeping, touch at most this many niches
POST /api/v1/tools/app_promoters1 unit

Who promotes an app (or a brand/product) on TikTok, from the videos the model has actually watched: the accounts promoting it (handle, followers, videos in the corpus, median views, first/last seen), the top videos (url, views, hook, hook type, production type, date) and the hook-type distribution across them. `app` accepts an App Store URL or id, a Google Play URL or package, a website domain, or a name. Every number is traceable to a watched video; returns insufficient-evidence below 3 videos. Free and read-only.

CLI: ugc app promoters

Arguments for app_promoters
FieldTypeRequiredDescription
appstringrequiredApp Store URL/id, Play URL/package, domain, or a name (e.g. "cal ai")
limitnumberdefault 10How many top videos and accounts to return
minConfidencenumberdefault 0.5Ignore promotion edges below this confidence (0–0.99)
POST /api/v1/tools/entity_videos1 unit

Page through every watched video linked to a promoted entity (from app_promoters), newest first, with the extractor’s confidence and the verbatim evidence for each link: the caption link, bio link, anchor, on-screen or spoken name, or partner hashtag. Use it to audit an app_promoters answer video by video. Free and read-only.

CLI: ugc entity videos

Arguments for entity_videos
FieldTypeRequiredDescription
entityIdstringrequiredThe entity id from app_promoters (ent_…)
cursorstringoptionalOpaque cursor from a previous page
limitnumberdefault 20
minConfidencenumberdefault 0Ignore edges below this confidence
POST /api/v1/tools/upload_video1 unit

Upload your own MP4 or MOV (up to 3 MiB through this JSON tool) as a private workspace video. Requires a live plan or trial and never adds the video to the shared corpus.

CLI: ugc upload video

Arguments for upload_video
FieldTypeRequiredDescription
filenamestringrequired
contentType"video/mp4" | "video/quicktime"optional
contentBase64stringrequired
POST /api/v1/tools/upload_list1 unit

List this workspace's private uploaded videos and watch status.

CLI: ugc upload list · ugc uploads list

POST /api/v1/tools/upload_remove1 unit

Delete one of this workspace's private uploads, its stored bytes, analysis, and any run artifacts derived from it.

CLI: ugc upload remove · ugc uploads remove

Arguments for upload_remove
FieldTypeRequiredDescription
videoIdstringrequired
POST /api/v1/tools/hook_predict1 unit

Forecast how a hook or script idea is likely to perform BEFORE you shoot it, using the videos most similar to it that the model has actually watched. Returns comparable videos with real view counts, the median/top-decile outcome, which hook types and angles the winners used, and what separates the top performers from the rest. Use whenever the user proposes a hook, script, or concept.

CLI: ugc hook predict

Arguments for hook_predict
FieldTypeRequiredDescription
textstringrequiredThe hook line, script, or concept to evaluate
nichestringoptionalRestrict comparables to a corpus niche slug (see corpus_niches)
limitnumberdefault 20How many comparables to retrieve
POST /api/v1/tools/corpus_build1 unit

Operator-only. Pre-build the corpus for one seed niche (or all of them): paginate searches and hashtags to ingest metadata cheaply, then fully watch the top-viewed unwatched videos in that niche. Run ahead of demand so later research questions are instant queries instead of live crawls.

CLI: ugc corpus build

Arguments for corpus_build
FieldTypeRequiredDescription
nichestringdefault "all"Niche slug from the seed list, or "all" for every niche
pagesPerQuerynumberdefault 2Pages per search/hashtag
watchPerNichenumberdefault 10Top unwatched videos to fully watch per niche (the paid step)
minViewsnumberdefault 20000Only watch videos above this view count
ingestOnlybooleandefault falseSkip the watching phase entirely
concurrencynumberdefault 3Niches processed in parallel (provider calls are ~30s each)
skipCoveredbooleandefault trueSkip niches that already have enough coverage — makes reruns resumable
coveredThresholdnumberdefault 150Videos that count as covered
POST /api/v1/tools/corpus_niches1 unit

List the seed niches and how much of the corpus each one covers (videos ingested and fully watched). Use to find gaps before running corpus_build.

CLI: ugc corpus niches

POST /api/v1/tools/track_add1 unit

Start tracking a target for continuous collection: an account handle, hashtag, keyword, or TikTok sound ID. Watchers poll active targets and ingest+watch new videos.

CLI: ugc track add

Arguments for track_add
FieldTypeRequiredDescription
kind"account" | "hashtag" | "keyword" | "sound"required
valuestringrequiredHandle (no @), hashtag (no #), keyword phrase, or sound ID
platform"tiktok" | "instagram"default "tiktok"
labelstringoptional
POST /api/v1/tools/track_list1 unit

List tracked targets and when they last ran.

CLI: ugc track list

POST /api/v1/tools/watcher_run10 units

Run one watcher sweep: for each active tracked target, pull latest videos, ingest, then fully watch the top-viewed videos that have no analysis yet. Intended to be invoked on a schedule.

CLI: ugc watcher run

Arguments for watcher_run
FieldTypeRequiredDescription
maxWatchPerTargetnumberdefault 2
pullLimitnumberdefault 20
POST /api/v1/tools/audit_report10 units

Produce a shareable markdown UGC audit for an account: pulls the account, watches its top outlier videos, and synthesizes performance shape + winning hooks + 3 copyable video concepts. The flagship report — takes a few minutes.

CLI: ugc audit report

Arguments for audit_report
FieldTypeRequiredDescription
platform"tiktok" | "instagram"default "tiktok"
handlestringrequired
limitnumberdefault 30Videos to pull for the baseline
maxWatchnumberdefault 4Outlier videos to fully watch
POST /api/v1/tools/ads_search1 unit

Search the Meta Ad Library (EU coverage: all ads delivered to the EU in the last ~12 months) by free text or Facebook page IDs. Reveals which paid creatives competitors run, how long they have run (longevity = winner signal), and EU reach. Requires META_AD_LIBRARY_TOKEN.

CLI: ugc ads search

Arguments for ads_search
FieldTypeRequiredDescription
searchTermsstringoptionalFree-text search over ad content, e.g. an app name
pageIdsarrayoptionalFacebook page IDs to pull all ads for
activeOnlybooleandefault false
limitnumberdefault 25
POST /api/v1/tools/video_info1 unit

Fetch metadata for a single video: stats (views/likes/comments/shares), caption, hashtags, duration, posting date, and the music/sound used (title, author, original-sound flag). Ingests into the corpus.

CLI: ugc video info

Arguments for video_info
FieldTypeRequiredDescription
urlstringrequiredTikTok or Instagram video/reel URL
POST /api/v1/tools/video_transcript1 unit

Get the spoken transcript of a video (provider-side, no download needed).

CLI: ugc video transcript

Arguments for video_transcript
FieldTypeRequiredDescription
urlstringrequiredTikTok or Instagram video/reel URL
POST /api/v1/tools/video_sound1 unit

Identify the music/sound used in a video from platform metadata: title, author, whether it is an original sound, and how many videos use it.

CLI: ugc video sound

Arguments for video_sound
FieldTypeRequiredDescription
urlstringrequiredTikTok or Instagram video/reel URL
POST /api/v1/tools/video_watch10 units

WATCH a video with a multimodal LLM and extract its creative anatomy: hook (first 2s), hook type, pacing, on-screen text, script beats with timestamps, CTA, emotional angle, creator archetype, visual style, transcript, and a why-it-works summary. Cached: returns the stored analysis if this video was already watched. This is the core primitive.

CLI: ugc video watch

Arguments for video_watch
FieldTypeRequiredDescription
urlstringrequiredTikTok or Instagram video/reel URL
forcebooleanoptionalRe-watch even if a cached analysis exists
subjectShape"app" | "dtc-physical" | "dtc-consumable" | "service"optionalPicks the analyst framing: app, dtc-physical, dtc-consumable or service
POST /api/v1/tools/video_similar1 unit

Find videos in the corpus similar to a given video or free-text description, via embedding similarity over transcript+creative-analysis. Complement with sound_videos (same sound) for trend-cloning.

CLI: ugc video similar

Arguments for video_similar
FieldTypeRequiredDescription
urlstringoptionalTikTok or Instagram video/reel URL
textstringoptionalFree-text description to search by instead of a URL
limitnumberdefault 10
POST /api/v1/tools/account_pull1 unit

Fetch an account profile and its recent videos (with stats and sounds) and ingest everything into the corpus. Returns the profile and the video list.

CLI: ugc account pull

Arguments for account_pull
FieldTypeRequiredDescription
platform"tiktok" | "instagram"default "tiktok"
handlestringrequiredAccount handle, without @
limitnumberdefault 30Max recent videos to pull
POST /api/v1/tools/account_audit10 units

Pull an account and compute its performance shape: median views, outlier videos (≥3x account median), posting cadence, and top sounds/hashtags. The raw material for an account audit report; follow up with video_watch on the outliers.

CLI: ugc account audit

Arguments for account_audit
FieldTypeRequiredDescription
platform"tiktok" | "instagram"default "tiktok"
handlestringrequired
limitnumberdefault 50
POST /api/v1/tools/sound_videos1 unit

List videos using a specific sound — the strongest "same trend" signal. TikTok takes a music ID (from video_info / video_sound); Instagram takes an audio_id, which only /v1/instagram/post returns. Ingests results into the corpus.

CLI: ugc sound videos

Arguments for sound_videos
FieldTypeRequiredDescription
soundIdstringrequiredTikTok music/sound ID, or Instagram audio_id
platform"tiktok" | "instagram"optionalPlatform to search — "tiktok" (default) or "instagram". Instagram is live as of P7; see docs/ops/instagram-go-no-go.md.
cursorstringoptional
POST /api/v1/tools/hashtag_videos1 unit

List TikTok videos or Instagram reels for a hashtag. Ingests results into the corpus.

CLI: ugc hashtag videos

Arguments for hashtag_videos
FieldTypeRequiredDescription
tagstringrequiredHashtag, with or without #
platform"tiktok" | "instagram"optionalPlatform to search — "tiktok" (default) or "instagram". Instagram is live as of P7; see docs/ops/instagram-go-no-go.md.
cursorstringoptional
POST /api/v1/tools/search_videos1 unit

Keyword-search TikTok videos or Instagram reels (discovery entry point for a niche, e.g. "calorie tracking app"). Ingests results into the corpus.

CLI: ugc search videos

Arguments for search_videos
FieldTypeRequiredDescription
querystringrequired
platform"tiktok" | "instagram"optionalPlatform to search — "tiktok" (default) or "instagram". Instagram is live as of P7; see docs/ops/instagram-go-no-go.md.
cursorstringoptional
POST /api/v1/tools/trending_videos1 unit

List the reels Instagram is currently promoting platform-wide — a zero-query discovery surface for format trends. Instagram only; unpaginated. Ingests results into the corpus.

CLI: ugc trending videos

Arguments for trending_videos
FieldTypeRequiredDescription
platform"tiktok" | "instagram"optionalInstagram only today; defaults to "instagram".
POST /api/v1/tools/video_comments1 unit

Fetch comments on a TikTok video or Instagram reel: author handle, verbatim text, like count and posting time. `limit` is a target the client pages towards (TikTok returns 20 per page, Instagram 15); each page is one provider credit.

CLI: ugc video comments

Arguments for video_comments
FieldTypeRequiredDescription
urlstringrequiredTikTok or Instagram video/reel URL
limitnumberoptional
cursorstringoptional
POST /api/v1/tools/corpus_stats1 unit

Summary of what is already in the corpus: video/account/analysis counts, top hook types, and most-seen sounds. Use before scraping more.

CLI: ugc corpus stats