Telegram Channel Stats
CanaliStatisticheCategoriePaesi
InserzionistiAnnunci
Accedi
Telegram Channel Stats

Servizio spy per Telegram Ads e archivio pubblico. Ricerca, avvisi, analytics e API — tutto in un posto.

live
82,6K
creatività
45K
inserzionisti
5,4 Mln
canali nel pool

Esplora

  • Canali
  • Inserzionisti
  • Annunci
  • Archivio
  • Tendenze

Categorie

  • Nicchie
  • Paesi
  • Regioni
  • App di pagamento
  • Mini-app
  • Statistiche canali

Risorse

  • Chi siamo
  • Prezzi
  • API pubblica
  • Aggiungi un canale
  • Blog
  • Wiki
  • Glossario
  • FAQ

Famiglia di prodotti G.Media

Creiamo ciò che merita attenzione e fiducia.

Vedi la famiglia completa →
Ad intelligenceLIVE
Telegram Ads Spy
tgadsspy.com

Archivio pubblico di tutta la pubblicità Telegram. Ricerca, avvisi, analisi.

82,6Kcreatività rivali

HubNEW
Telegram Ads Hub
tgads.net

Where Telegram advertisers learn, decide, launch.

45Kinserzionisti da studiare

SelezioneNEW
Best Mini Apps
bestapps.tg

Best Telegram mini-apps · handpicked monthly by the G.Media team.

27nicchie · selezione manuale

ClassificaNEW
Top Mini Apps
topapps.tg

Public daily leaderboard of Telegram mini-apps by active users.

1,4Knella classifica live

Social · TelegramLIVE
Wall
wall.tg

Social Telegram Mini App for creators · powered by TON.

119,675utenti

G.Media·DMCC, JLT, Dubai·[email protected]·G MEDIA PARTNERS EUROPE d.o.o.

© 2026 Telegram Channel Stats.
PrivacyTerminiDMCA
for developerssitemap.xmlrss.xmlllms.txtopenapi.json
Home/Riferimento API

API

Public API reference

Read-only JSON (and CSV for exports). Optional X-Api-Key lifts per-IP rate limits and unlocks larger page sizes. CORS open. All responses cache-friendly.

Base URL: https://tgadsspy.com

OpenAPI 3.1 spec: /api/v1/openapi.json — feed it to openapi-typescript, openapi-generator-cli or Postman/Insomnia for a typed client in any language.

Pagination: all list endpoints accept limit and offset. The response meta block carries the running total.

Subscribe to alerts via our bot: @tgadsspybot — use /subscribe crypto or any keyword.

Authentication & rate limits

All endpoints work without an API key — you get the ANON tier. Pass X-Api-Key: <your-key> to unlock FREE or PRO limits. Key management lives on /account/api-keys.

PlanRate limitMax limitMax offsetAccess
ANON60 req / min (burst) · 1 / s sustained501 000no key required
FREE600 req / min · 10 / s sustained10010 000free signup
PRO6 000 req / min · 100 / s sustained500100 000paid plan

Request

Send the key in the X-Api-Key header:

curl -H 'X-Api-Key: tgak_••••••••••••••••' \
  'https://tgadsspy.com/api/v1/ads?limit=100'

Response headers

Every response carries plan context so you can monitor usage client-side:

HeaderMeaning
X-PlanTier resolved from your key (or ANON).
X-RateLimit-LimitBucket capacity for your tier.
X-RateLimit-RemainingTokens left after this request.
X-RateLimit-ResetSeconds until the bucket fully refills.
X-Request-IdTrace id for support. Echoed back if you send it in the request, otherwise generated server-side. Include it when reporting issues.
X-Response-Time-MsServer-side latency in milliseconds (gate entry → response). Useful for client-side performance dashboards.

429 Too Many Requests

When the bucket is empty we return HTTP 429. The body includes an upgradeHint pointing at the next tier:

{
  "error": "rate_limited",
  "plan": "ANON",
  "retryAfter": 12,
  "upgradeHint": "Get a free API key for 10× higher limits."
}

Respect the Retry-After header. If you hit limits repeatedly, upgrade at /account/api-keys.

Endpoints

  • GET/rss.xml
  • GET/feed.json
  • GET/api/healthz
  • GET/api/product
  • GET/api/v1/ecosystem
  • GET/api/v1/glossary
  • GET/api/v1/glossary.csv
  • GET/api/v1/stats
  • GET/api/v1/miniapps
  • GET/api/v1/miniapps.csv
  • GET/api/v1/miniapps/<username>
  • GET/api/v1/ads
  • GET/api/v1/ads.csv
  • GET/api/v1/cashier-creatives
  • GET/api/v1/cashier-creatives.csv
  • GET/api/v1/channels
  • GET/api/v1/advertisers
  • GET/api/v1/advertisers.csv
  • GET/api/v1/advertisers/:slug
  • GET/api/v1/channels/:username/aliases
  • GET/api/v1/niches
  • GET/api/v1/categories
  • GET/api/v1/categories.csv
  • GET/api/v1/niches.csv
  • GET/api/v1/geos
  • GET/api/v1/geos.csv
  • GET/api/v1/comparisons
  • GET/api/v1/comparisons/stats
  • GET/api/v1/comparisons/:type/:canonical
  • GET/api/v1/comparisons/related/:type/:canonical
  • GET/api/v1/comparisons.csv
  • GET/api/v1/trends
  • GET/api/v1/analytics
  • GET/api/v1/feeds
  • GET/api/v1/analytics/* (Phase 2)
  • GET/api/v1/analytics/advertiser-creatives.csv
  • GET/api/v1/analytics/niche-leaderboard.csv
  • GET/api/v1/analytics/spend-estimate.csv
  • GET/api/v1/analytics/geo-snapshot.csv
  • GET/api/v1/analytics/advertiser-timeline.csv
  • GET/api/v1/analytics/niche-pricing.csv
  • GET/api/v1/analytics/channel-ad-load.csv
  • GET/api/v1/analytics/cta-domains.csv
  • GET/api/v1/analytics/share-of-voice.csv
  • GET/api/v1/analytics/creative-fatigue.csv
  • GET/api/v1/analytics/frequency-distribution.csv
  • GET/api/v1/analytics/competitor-overlap.csv
GET/rss.xml— RSS feed — latest 50

Global RSS feed of the 50 most recent creatives. Also per-niche: /niches/<slug>/rss.xml

cURL

curl https://tgadsspy.com/rss.xml

Node

const r = await fetch('https://tgadsspy.com/rss.xml')
const xml = await r.text()
console.log(xml)

Python

import requests

r = requests.get('https://tgadsspy.com/rss.xml')
print(r.text)

Response

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
  <title>Telegram Ads Spy — latest creatives</title>
  <item>
    <title>...</title>
    <link>https://tgadsspy.com/ads/...</link>
    <pubDate>...</pubDate>
    <category>crypto</category>
    ...
  </item>
</channel>
</rss>
GET/feed.json— JSON Feed v1.1 — modern aggregator format

Same content stream as /rss.xml but in JSON Feed v1.1 spec (jsonfeed.org). Modern aggregators — Feedbin, Inoreader, NewsBlur, Reeder, Readwise — parse JSON natively. Each item has structured tags array (niche, geo:RU, lang:en, source:TON, cashier flag) для aggregator-side filtering. CORS *. Cache 5 min. CC-BY-4.0.

cURL

curl https://tgadsspy.com/feed.json

Node

const r = await fetch('https://tgadsspy.com/feed.json')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/feed.json')
print(r.json())

Response

{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Telegram Ads Spy — latest Telegram ads",
  "home_page_url": "https://tgadsspy.com/",
  "feed_url": "https://tgadsspy.com/feed.json",
  "items": [
    {
      "id": "https://tgadsspy.com/ads/abc123",
      "url": "https://tgadsspy.com/ads/abc123",
      "title": "...",
      "content_text": "...",
      "date_published": "2026-05-06T...",
      "tags": ["crypto", "geo:RU", "lang:ru", "source:TON", "cashier"],
      "_tgadsspy": { "advertiser": "...", "cta_url": "...", "is_cashier": true }
    }
  ],
  "_tgadsspy": { "license": "CC BY 4.0", "rss_alternate": "https://tgadsspy.com/rss.xml" }
}
GET/api/healthz— Health check

Cheap liveness probe. Useful for uptime monitors.

cURL

curl https://tgadsspy.com/api/healthz

Node

const r = await fetch('https://tgadsspy.com/api/healthz')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/healthz')
print(r.json())

Response

{"ok":true,"service":"tgadsspy","version":"0.0.1","ts":"..."}
GET/api/product— Product descriptor (machine-readable)

Single-call Telegram Ads Spy descriptor for AI clients and llmstxt.org consumers. Returns live stats (creatives/channels/cashier/mini-apps + glossary count), features narrative, ecosystem block (sister-products with Wall live_stats lazy-block), and data_feeds map. CORS *. Cache 5 min.

cURL

curl https://tgadsspy.com/api/product

Node

const r = await fetch('https://tgadsspy.com/api/product')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/product')
print(r.json())

Response

{
  "name": "tgadsspy",
  "tagline": "Telegram Ads Intelligence — public archive of all sponsored ads",
  "stats": { "creatives": 36742, "channels": 2046033, "advertisers": 14908, "cashier_creatives": 412, "mini_app_bots": 18247, "..." },
  "features": { "creative_archive": "...", "cashier_vertical": "...", "mini_apps": "...", "programmatic_seo": { "glossary_terms": 74, "..." } },
  "ecosystem": { "company": "G.media", "sister_products": [{ "name": "Wall", "live_stats": {...}, "..." }] },
  "data_feeds": { "ecosystem_api": "https://tgadsspy.com/api/v1/ecosystem", "..." },
  "meta": { "schema_version": "1.1", "..." }
}
GET/api/v1/ecosystem— G.Media ecosystem feed (combined)

Single envelope returning the entire G.Media product family — replaces two-fetch pattern (/api/product + wall.tg/api/product) for cross-product consumers. Includes legal entity, products (Telegram Ads Spy + Wall) with localised pitches, bots (flagship/assistant/ai/utility), TLD-family domains, live Telegram Ads Spy stats, Wall daily snapshot (cron-mirrored, fallback to WALL_PRODUCT_FACTS if not yet collected). CORS *. Cache 5 min.

cURL

curl https://tgadsspy.com/api/v1/ecosystem

Node

const r = await fetch('https://tgadsspy.com/api/v1/ecosystem')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/ecosystem')
print(r.json())

Response

{
  "ecosystem": { "name": "G.Media", "founder": {...}, "hq": {...} },
  "products": [{ "id": "tgadsspy", "pitch": {"en":"...","ru":"..."} }, { "id": "wall", "..." }],
  "bots": [{ "handle": "gidbot", "category": "flagship", "..." }, "..."],
  "domains": [{ "url": "https://g.media", "canonical": true }, "..."],
  "live": {
    "tgadsspy": { "stats": { "creatives": 36742, "cashier_creatives": 412, "mini_app_bots": 18247, "..." } },
    "wall":     { "stats": { "users_total": 70663, "branches_count": 18, "..." } }
  },
  "data_feeds": { "tgadsspy_*": "...", "wall_*": "..." },
  "meta": { "schema_version": "1.0", "license": "CC BY 4.0" }
}
GET/api/v1/glossary— Glossary feed (all terms, EN+RU)

Single-call public JSON feed of every Telegram-ads glossary term — 74+ entries with EN+RU localised copy, category and related-term cross-links. Filterable by ?category=ad-types|metrics|technical|... (validated, returns 400 on unknown) or ?slug=a,b,c (regex-validated). Replaces crawling /info/<slug> pages individually. Pure import from lib/glossary.ts, no DB hit. CORS *. Cache 24h.

ParamTypeDescription
categorystringplatform | ad-types | metrics | actors | strategies | compliance | technical
slugcomma-separatedFilter to specific entries. Example: ?slug=telegram-stars,cashier,xtr

cURL

curl "https://tgadsspy.com/api/v1/glossary?category=ad-types"

Node

const r = await fetch('https://tgadsspy.com/api/v1/glossary?category=ad-types')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/glossary?category=ad-types')
print(r.json())

Response

{
  "data": [
    {
      "slug": "telegram-stars",
      "category": "platform",
      "url": "https://tgadsspy.com/info/telegram-stars",
      "en": { "term": "Telegram Stars (XTR)", "definition": "..." },
      "ru": { "term": "Telegram Stars (XTR)", "definition": "..." },
      "related": [
        { "slug": "cashier", "url": "https://tgadsspy.com/info/cashier" }
      ]
    }
  ],
  "meta": {
    "total": 74,
    "categories": ["platform","ad-types","metrics","actors","strategies","compliance","technical"],
    "by_category": { "platform": 5, "ad-types": 8, "..." },
    "license": "CC BY 4.0",
    "source": "lib/glossary.ts"
  }
}
GET/api/v1/glossary.csv— Glossary feed — CSV mirror

Same dataset as /api/v1/glossary but in flat 8-column CSV format — slug, category, url, term_en, definition_en, term_ru, definition_ru, related_slugs (pipe-separated). Researcher-friendly for spreadsheet analysis and academic citations. Same filters as JSON. OWASP formula-injection escaped. CORS *. Cache 24h.

ParamTypeDescription
categorystringplatform | ad-types | metrics | actors | strategies | compliance | technical
slugcomma-separatedFilter to specific entries

cURL

curl "https://tgadsspy.com/api/v1/glossary.csv?category=ad-types" > glossary-ad-types.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/glossary.csv?category=ad-types')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/glossary.csv?category=ad-types')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

slug,category,url,term_en,definition_en,term_ru,definition_ru,related_slugs
telegram-stars,platform,https://tgadsspy.com/info/telegram-stars,Telegram Stars (XTR),"Telegram's native in-app currency...",Telegram Stars (XTR),"Внутренняя валюта Telegram...",cashier|sponsored-invoice|mini-app|sponsored-message
cashier,ad-types,https://tgadsspy.com/info/cashier,Cashier creative,"A sponsored message that triggers a payment flow...",Cashier-креатив,"Спонсорское сообщение, запускающее платёжный flow...",telegram-stars|sponsored-invoice|premium-giveaway|main-app
...
GET/api/v1/stats— Aggregate stats

Global counts (creatives, channels, advertisers, impressions) plus today-only deltas and payment-source breakdown. Cached 60s.

cURL

curl https://tgadsspy.com/api/v1/stats

Node

const r = await fetch('https://tgadsspy.com/api/v1/stats')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/stats')
print(r.json())

Response

{
  "data": {
    "creatives": 1234,
    "channels": 156,
    "advertisers": 89,
    "impressions": 4321,
    "paymentBreakdown": { "EUR_ADS_CABINET": 1100, "TON": 134 },
    "today": {
      "creatives": 48,
      "impressions": 92,
      "advertisers": 5,
      "vsYesterdayPct": 12
    },
    "ts": "2026-04-19T..."
  }
}
GET/api/v1/miniapps— List Telegram mini-apps

Leaderboard of bots running main-app mini-apps. Sortable by active users, Telegram official rank, Stars rating level, or D7 trending growth. Filter by niche or sponsored-enabled.

ParamTypeDescription
sortmau|stars|tgrank|trendingmau = botActiveUsers DESC (default). stars = botStarsRatingLevel DESC. tgrank = popularBotsRank ASC NULLS LAST (Telegram curation). trending = D7 growth % via BotMauSnapshot CTE.
nichestringExact niche slug from INDEXABLE list (crypto, gambling, finance, games, trading, …). Validated server-side, unknown slugs ignored.
sponsored1|true|0|falseWhen 1/true, return only mini-apps with active Telegram Ads (botSponsoredEnabled=true).
limitint 1–500Default 50. Max depends on plan: ANON 50, FREE 100, PRO 500.
offsetintFor pagination. Default 0.

cURL

curl "https://tgadsspy.com/api/v1/miniapps?sort=trending&niche=crypto&limit=20"

Node

const r = await fetch('https://tgadsspy.com/api/v1/miniapps?sort=trending&niche=crypto&limit=20')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/miniapps?sort=trending&niche=crypto&limit=20')
print(r.json())

Response

{
  "data": [
    {
      "username": "minigame_bot",
      "title": "Mini Game",
      "avatarUrl": "/m/ab/abc123.jpg",
      "botActiveUsers": 1245000,
      "botStarsRatingLevel": 12,
      "botSponsoredEnabled": true,
      "lastBotEnrichmentAt": "2026-05-05T...",
      "popularBotsRank": 7,
      "botNiche": "games",
      "growthPct": 18.4
    }
  ],
  "meta": { "total": 132, "limit": 20, "offset": 0, "plan": "FREE", "sort": "trending" }
}
GET/api/v1/miniapps.csv— Mini-app leaderboard — CSV mirror

10-column CSV mirror of /api/v1/miniapps for spreadsheet/research workflows. Same filters and sort options (mau/stars/tgrank — no trending CTE for CSV). Requires X-Api-Key — ANON blocked (matches /api/v1/cashier-creatives.csv pattern). OWASP formula-injection escaped. Plan-tier limit cap: FREE 100, PRO 500.

ParamTypeDescription
sortmau|stars|tgrankmau = botActiveUsers DESC (default). stars = botStarsRatingLevel DESC. tgrank = popularBotsRank ASC NULLS LAST.
nichestringExact niche slug from INDEXABLE list.
sponsored1|true|0|falseReturn only sponsored-enabled mini-apps.
stars101|true|0|falseFilter botStarsRatingLevel >= 10.
limitint 1–500Default 500. Plan caps: FREE 100, PRO 500.

cURL

curl -H "X-Api-Key: $KEY" "https://tgadsspy.com/api/v1/miniapps.csv?sort=stars&niche=crypto" > miniapps-crypto.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/miniapps.csv?sort=stars&niche=crypto')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/miniapps.csv?sort=stars&niche=crypto')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

username,title,niche,mau,stars_level,popular_bots_rank,sponsored_enabled,avatar_url,last_enriched_at,profile_url
notcoin_bot,Notcoin,crypto,42000000,23,1,true,https://tgadsspy.com/m/ab/abc.jpg,2026-05-06T...,https://tgadsspy.com/miniapps/notcoin_bot
catizen_bot,Catizen,crypto,18500000,18,3,true,...,...,https://tgadsspy.com/miniapps/catizen_bot
...
GET/api/v1/miniapps/<username>— Mini-app detail with time-series

Single bot detail: full cashier-signals + last 30 BotMauSnapshot points (takenAt + activeUsers + starsLevel) для researcher sparkline / growth analysis. 404 если bot не enriched (botHasMainApp != true) или username не существует.

ParamTypeDescription
usernamestringBot username (path param). Lowercased, validated against `^[a-z0-9_]{3,32}$`.

cURL

curl "https://tgadsspy.com/api/v1/miniapps/notcoin_bot"

Node

const r = await fetch('https://tgadsspy.com/api/v1/miniapps/notcoin_bot')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/miniapps/notcoin_bot')
print(r.json())

Response

{
  "data": {
    "username": "notcoin_bot",
    "title": "Notcoin",
    "description": "Tap-to-earn TON mini-app",
    "avatarUrl": "/m/cd/cd456.jpg",
    "botActiveUsers": 42000000,
    "botStarsRatingLevel": 23,
    "botStarsRatingStars": 1240000,
    "botSponsoredEnabled": true,
    "popularBotsRank": 1,
    "popularBotsRankedAt": "2026-05-05T...",
    "botNiche": "crypto",
    "lastBotEnrichmentAt": "2026-05-05T...",
    "timeseries": [
      { "takenAt": "2026-04-06T...", "activeUsers": 38500000, "starsLevel": 21 },
      { "takenAt": "2026-04-07T...", "activeUsers": 39100000, "starsLevel": 21 }
    ]
  },
  "meta": { "plan": "FREE" }
}
GET/api/v1/ads— List creatives

Paginated feed of ad creatives. All filters compose; default sort is newest first.

ParamTypeDescription
qstringCase-insensitive substring match on text or title.
advertiserstringFilter by advertiser slug (see /api/v1/advertisers). Returns empty array for unknown slug.
paymentSourceTON|EUR_ADS_CABINET|UNKNOWNExact enum.
sourceton|eur|allShorter alias for paymentSource.
destall|telegram|externalFilter by CTA destination: telegram (t.me links) or external (web URLs).
nichestringExact niche slug (crypto, trading, vpn, …). Granular taxonomy.
categoryfinance|gambling|tech|content|commerce|lifeCoarse super-group filter — expands to all niches inside. Mutually exclusive with niche (niche wins if both passed).
geostringISO country code, auto-uppercased.
langstringCreative language hint.
sortnew|reachSort order: new = firstSeenAt desc (default), reach = reachEstimate desc.
daysint 1–365Limit to creatives first seen in the last N days.
sinceISO timestampCreatives first seen after this timestamp (ISO 8601). Used by live polling.
limitint 1–500Default 50. Max depends on plan: ANON 50, FREE 100, PRO 500.
offsetintFor pagination. Default 0.

cURL

curl "https://tgadsspy.com/api/v1/ads?niche=crypto&source=eur&limit=20"

Node

const r = await fetch('https://tgadsspy.com/api/v1/ads?niche=crypto&source=eur&limit=20')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/ads?niche=crypto&source=eur&limit=20')
print(r.json())

Response

{
  "data": [
    {
      "id": "c...",
      "title": "P's Trading Journal",
      "text": "Private Crypto trading journal...",
      "paymentSource": "EUR_ADS_CABINET",
      "niche": "crypto",
      "category": "finance",
      "geo": null,
      "lang": null,
      "firstSeenAt": "2026-04-18T...",
      "lastSeenAt":  "2026-04-18T...",
      "placementCount": 0,
      "impressionCount": 1,
      "reachEstimate": "0",
      "advertiserId": "...",
      "advertiserSlug": "crypto-signals",
      "advertiserName": "@cryptosignals",
      "mediaUrl": "https://cdn4.telesco.pe/...jpg",
      "ctaButtonText": "VIEW BOT",
      "ctaUrl": "https://t.me/...",
      "targetAvatarUrl": null,
      "targetTitle": null
    }
  ],
  "meta": { "total": 31, "limit": 20, "offset": 0, "plan": "ANON" }
}
GET/api/v1/ads.csv— Export creatives as CSV

Same filters as /api/v1/ads. Returns text/csv with 20 columns (including category between paymentSource and niche; minDisplaySec/maxDisplaySec at the end), up to 500 rows. Attachment download.

ParamTypeDescription
qstringSame as /api/v1/ads.
advertiserstringFilter by advertiser slug. Same as /api/v1/ads.
sourceton|eurSame as /api/v1/ads.
nichestringSame as /api/v1/ads.
categoryfinance|gambling|tech|content|commerce|lifeCoarse super-group. Mutually exclusive with niche.
geostringSame as /api/v1/ads.
limitint 1–500Default 500.

cURL

curl -O "https://tgadsspy.com/api/v1/ads.csv?niche=crypto&limit=100"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/ads.csv?niche=crypto&limit=100')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/ads.csv?niche=crypto&limit=100')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

id,title,text,paymentSource,category,niche,geo,lang,ctaButtonText,ctaUrl,mediaUrl,advertiser,advertiserSlug,placementCount,impressionCount,reachEstimate,firstSeenAt,lastSeenAt,minDisplaySec,maxDisplaySec
c...,P's Trading Journal,...,EUR_ADS_CABINET,finance,crypto,,,VIEW BOT,https://t.me/...,https://cdn4...jpg,,,0,1,0,2026-04-18T...,2026-04-18T...,5,30
GET/api/v1/cashier-creatives— List cashier creatives (Stars / giveaway)

Pre-filtered feed of cashier creatives — Telegram Stars инвойсы (XTR + classic currencies) и Premium giveaway / giveaway_results. Symmetric pair to /api/v1/miniapps (Channel-side cashier surface). Default sort newest first; meta.byType returns invoice/giveaway counts under the active filter.

ParamTypeDescription
typeinvoice|giveawayDiscriminator. Omit for both. invoice = OR(invoiceCurrency NOT NULL, mediaType=invoice). giveaway = OR(giveawayPrize NOT NULL, mediaType IN giveaway/giveaway_results).
currencystring3–4 uppercase letters. XTR = Telegram Stars, иначе ISO 4217 (USD, EUR, RUB, …). Validates server-side.
advertiserstringFilter by advertiser slug (see /api/v1/advertisers). Returns empty array for unknown slug.
nichestringNiche slug (crypto, gambling, finance, games, trading, …).
geostringAdvertiser-intent geo (ISO-3166 alpha-2).
servstringSponsoredImpression.region (audience served-to). Distinct from `geo`.
langstringCreative language (en, ru, …).
sortnew|reachnew = firstSeenAt DESC (default). reach = reachEstimate DESC.
daysint 1–365Recent window in days. ANON clamped to ≤7.
sinceISO timestampCursor for live polling. ANON clamped to last 24h.
limitint 1–500Default 50. Max depends on plan: ANON 50, FREE 100, PRO 500.
offsetintFor pagination. Default 0.

cURL

curl "https://tgadsspy.com/api/v1/cashier-creatives?type=invoice&currency=XTR&limit=20"

Node

const r = await fetch('https://tgadsspy.com/api/v1/cashier-creatives?type=invoice&currency=XTR&limit=20')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/cashier-creatives?type=invoice&currency=XTR&limit=20')
print(r.json())

Response

{
  "data": [
    {
      "id": "c...",
      "title": "Premium Stars Pack",
      "text": "Get 1000 stars instantly",
      "paymentSource": "TON",
      "niche": "crypto",
      "geo": null,
      "lang": "en",
      "isCashierCreative": true,
      "invoiceCurrency": "XTR",
      "invoiceTotalAmount": "1000",
      "invoiceTitle": "Stars Pack",
      "giveawayPrize": null,
      "giveawayMonths": null,
      "ctaButtonText": "BUY",
      "ctaUrl": "https://t.me/example_bot?start=stars",
      "ctaTargetUsername": "example_bot",
      "advertiserSlug": "stars-shop",
      "advertiserName": "Stars Shop",
      "reachEstimate": "12500",
      "firstSeenAt": "2026-05-04T...",
      "lastSeenAt": "2026-05-05T..."
    }
  ],
  "meta": {
    "total": 47,
    "byType": { "invoice": 32, "giveaway": 15 },
    "limit": 20,
    "offset": 0,
    "plan": "FREE"
  }
}
GET/api/v1/cashier-creatives.csv— Export cashier creatives as CSV

Same filters as /api/v1/cashier-creatives. Returns text/csv with 27 columns (extends ads.csv с invoice* + giveaway* + ctaTargetUsername полями), up to 500 rows. Attachment download. Requires X-Api-Key (FREE+ plan, anon blocked).

ParamTypeDescription
typeinvoice|giveawaySame as /api/v1/cashier-creatives.
currencystringXTR or ISO 4217. Same as /api/v1/cashier-creatives.
advertiserstringFilter by advertiser slug.
nichestringNiche slug.
geostringAdvertiser-intent geo.
servstringAudience served-to region.
langstringCreative language.
limitint 1–500Default 500.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/cashier-creatives.csv?type=invoice&currency=XTR&limit=100"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/cashier-creatives.csv?type=invoice&currency=XTR&limit=100')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/cashier-creatives.csv?type=invoice&currency=XTR&limit=100')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

id,title,text,paymentSource,niche,geo,lang,isCashierCreative,invoiceCurrency,invoiceTotalAmount,invoiceTitle,giveawayPrize,giveawayMonths,giveawayWinnersCount,giveawayUntilDate,giveawayCountriesIso2,ctaButtonText,ctaUrl,ctaTargetUsername,mediaUrl,advertiser,advertiserSlug,placementCount,impressionCount,reachEstimate,firstSeenAt,lastSeenAt
c...,Premium Stars Pack,Get 1000 stars,TON,crypto,,en,true,XTR,1000,Stars Pack,,,,,,BUY,https://t.me/example_bot,example_bot,,,,0,1,12500,2026-05-04T...,2026-05-05T...
GET/api/v1/channels— List channels

Telegram channels we track, sorted by member count desc.

ParamTypeDescription
qstringCase-insensitive substring match on username or title.
langstringChannel language filter.
categorystringCategory filter (news, crypto, …).
minMembersintOnly channels with members ≥ this value.
sponsoredeligibleOnly channels eligible for Telegram sponsored messages.
limitint 1–500Default 50. Max depends on plan: ANON 50, FREE 100, PRO 500.
offsetintDefault 0.

cURL

curl "https://tgadsspy.com/api/v1/channels?sponsored=eligible&minMembers=100000"

Node

const r = await fetch('https://tgadsspy.com/api/v1/channels?sponsored=eligible&minMembers=100000')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/channels?sponsored=eligible&minMembers=100000')
print(r.json())

Response

{
  "data": [
    {
      "id": "...",
      "username": "durov",
      "title": "Pavel Durov",
      "lang": "en",
      "category": "personal",
      "members": 10248881,
      "avgViews": 819910,
      "estimatedCpm": null,
      "isVerified": true,
      "isSponsoredEligible": true,
      "lastSnapshotAt": "2026-04-19T..."
    }
  ],
  "meta": { "total": 108, "limit": 50, "offset": 0 }
}
GET/api/v1/advertisers— List advertisers

Advertisers we identified from CTA URLs (domains + Telegram handles). Default sort: creative count desc.

ParamTypeDescription
qstringCase-insensitive match on name, slug, or domain.
domainstringPartial domain match (case-insensitive).
tgUsernamestringExact Telegram username match (case-insensitive). Use without @ prefix.
sortpopular|new|recentSort: popular = most creatives (default), new = firstSeenAt desc, recent = lastSeenAt desc.
limitint 1–500Default 50. Max depends on plan: ANON 50, FREE 100, PRO 500.
offsetintDefault 0.

cURL

curl "https://tgadsspy.com/api/v1/advertisers?q=crypto&limit=20"

Node

const r = await fetch('https://tgadsspy.com/api/v1/advertisers?q=crypto&limit=20')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/advertisers?q=crypto&limit=20')
print(r.json())

Response

{
  "data": [
    {
      "id": "...",
      "slug": "tg-mrp_tradingbot",
      "name": "@MrP_Tradingbot",
      "domain": null,
      "tgUsername": "mrp_tradingbot",
      "creativeCount": 1,
      "firstSeenAt": "2026-04-18T...",
      "lastSeenAt":  "2026-04-18T..."
    }
  ],
  "meta": { "total": 10, "limit": 20, "offset": 0 }
}
GET/api/v1/advertisers.csv— Advertiser index — CSV mirror

9-column CSV mirror of /api/v1/advertisers for competitive intelligence workflows. Sortable by popular/new/recent. Filterable by q/domain/niche. Requires X-Api-Key — ANON blocked (matches /api/v1/cashier-creatives.csv pattern). OWASP escape. Plan-tier limit cap: FREE 100, PRO 500.

ParamTypeDescription
qstringCase-insensitive search (name/slug/domain).
domainstringPartial domain filter.
nichestringExact primary niche slug.
sortpopular|new|recentDefault popular.
limitint 1–500Default 500. Plan caps: FREE 100, PRO 500.

cURL

curl -H "X-Api-Key: $KEY" "https://tgadsspy.com/api/v1/advertisers.csv?niche=crypto&sort=popular" > advertisers-crypto.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/advertisers.csv?niche=crypto&sort=popular')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/advertisers.csv?niche=crypto&sort=popular')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

slug,name,domain,tg_username,primary_niche,creative_count,first_seen_at,last_seen_at,profile_url
ftmo,FTMO,ftmo.com,ftmo,prop-firm,1240,2026-01-15T...,2026-05-06T...,https://tgadsspy.com/advertisers/ftmo
binance,Binance,binance.com,binance,crypto,890,2026-02-10T...,2026-05-06T...,https://tgadsspy.com/advertisers/binance
...
GET/api/v1/advertisers/:slug— Get advertiser by slug

Look up a single advertiser by their unique slug. Returns 404 for unknown slugs. Includes: primary niche, honeypot flag (anti-scrape Phase B decoy detection), discovery aggregates (channels promoting CTAs, t.me-post mention count, discovery sources), и domains[] array (all known domain mappings — main + .ru + .com + landing-pages).

ParamTypeDescription

cURL

curl "https://tgadsspy.com/api/v1/advertisers/tg-mrp_tradingbot"

Node

const r = await fetch('https://tgadsspy.com/api/v1/advertisers/tg-mrp_tradingbot')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/advertisers/tg-mrp_tradingbot')
print(r.json())

Response

{
  "data": {
    "id": "...",
    "slug": "tg-mrp_tradingbot",
    "name": "@MrP_Tradingbot",
    "domain": null,
    "tgUsername": "mrp_tradingbot",
    "creativeCount": 1,
    "firstSeenAt": "2026-04-18T...",
    "lastSeenAt": "2026-04-18T...",
    "primaryNiche": "trading",
    "isHoneypot": false,
    "channelsPromotedIn": 12,
    "tmePostsCount": 47,
    "discoverySources": ["tme-scraper", "gramesh-cta"],
    "domains": [
      {
        "domain": "mrp-trading.com",
        "rootDomain": "mrp-trading.com",
        "firstSeenAt": "2026-04-18T...",
        "lastSeenAt": "2026-05-17T...",
        "postsCount": 38,
        "channelsCount": 9,
        "source": "tme-scraper"
      }
    ]
  }
}
GET/api/v1/channels/:username/aliases— Fragment NFT-username aliases для канала

Telegram через Fragment marketplace (TON) разрешает на одном entity несколько usernames (multinames). Owner может attach/detach/sell aliases. Этот endpoint возвращает все известные variants — включая detached (с detachedAt set) для historical record. Resolves username через canonical Channel ИЛИ alias mapping. Use cases: brand monitoring, anti-squatting detection, Fragment marketplace research.

ParamTypeDescription

cURL

curl "https://tgadsspy.com/api/v1/channels/durov/aliases"

Node

const r = await fetch('https://tgadsspy.com/api/v1/channels/durov/aliases')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/channels/durov/aliases')
print(r.json())

Response

{
  "data": [
    {
      "alias": "durov",
      "source": "user-submit",
      "firstSeenAt": "2026-01-15T...",
      "lastSeenAt": "2026-05-17T...",
      "detachedAt": null
    },
    {
      "alias": "old_durov",
      "source": "gramesh-multiname",
      "firstSeenAt": "2025-08-01T...",
      "lastSeenAt": "2026-01-15T...",
      "detachedAt": "2026-01-15T..."
    }
  ],
  "meta": { "canonical": "durov", "total": 2, "plan": "FREE" }
}
GET/api/v1/niches— List niches with counts

All known niches (crypto, trading, vpn, gambling, tech, news, retail, finance, gaming, education, bots) with current counts and SEO-friendly metadata. Useful for building navigation or a niche directory.

cURL

curl https://tgadsspy.com/api/v1/niches

Node

const r = await fetch('https://tgadsspy.com/api/v1/niches')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/niches')
print(r.json())

Response

{
  "data": [
    {
      "slug": "crypto",
      "title": "Crypto ads on Telegram",
      "headline": "Crypto, Web3 and token ads",
      "description": "Every Bitcoin, Ethereum, TON...",
      "count": 12,
      "indexable": true,
      "url": "https://tgadsspy.com/niches/crypto",
      "feed": "https://tgadsspy.com/niches/crypto/rss.xml"
    }
  ],
  "meta": { "total": 11, "locale": "en" }
}
GET/api/v1/categories— List categories (coarse taxonomy) with niches inside

Coarse-grained taxonomy: 6 super-groups (Finance, Gambling, Tech, Content, Commerce, Lifestyle). Each item includes per-group total + niches[] with counts. Companion to /api/v1/niches at one level up. Use ?category=<group> as a filter on /api/v1/ads or /api/v1/cashier-creatives to expand to all niches inside.

cURL

curl https://tgadsspy.com/api/v1/categories

Node

const r = await fetch('https://tgadsspy.com/api/v1/categories')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/categories')
print(r.json())

Response

{
  "data": [
    {
      "slug": "finance",
      "label": "Finance & Crypto",
      "total": 1240,
      "nicheCount": 4,
      "niches": [
        { "slug": "crypto", "count": 850 },
        { "slug": "trading", "count": 220 },
        { "slug": "finance", "count": 130 },
        { "slug": "prop-firm", "count": 40 }
      ],
      "url": "https://tgadsspy.com/categories/finance"
    }
  ],
  "meta": { "total": 6, "locale": "en" }
}
GET/api/v1/categories.csv— Categories taxonomy as flat CSV

Flat denormalized CSV — one row per (category, niche) pair with niche_count + category_total. Suitable for Excel pivots and pandas import without JSON nesting.

cURL

curl https://tgadsspy.com/api/v1/categories.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/categories.csv')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/categories.csv')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

category_slug,category_label,niche_slug,niche_count,category_total
finance,Finance & Crypto,crypto,850,1240
finance,Finance & Crypto,trading,220,1240
finance,Finance & Crypto,finance,130,1240
finance,Finance & Crypto,prop-firm,40,1240
...
GET/api/v1/niches.csv— Niche distribution — CSV mirror

8-column CSV mirror of /api/v1/niches for spreadsheet/research workflows. Adds advertiser_count column для diversity analysis (количество distinct advertisers per niche). Researcher-friendly for ad-market vertical evolution studies. Public, no auth, 60s cache.

cURL

curl "https://tgadsspy.com/api/v1/niches.csv" > niches.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/niches.csv')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/niches.csv')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

slug,title,headline,count,advertiser_count,indexable,url,feed_url
crypto,Crypto ads on Telegram,"Crypto, Web3 and token ads",12450,1248,true,https://tgadsspy.com/niches/crypto,https://tgadsspy.com/niches/crypto/rss.xml
trading,Trading signals,"Trading signal services",8900,890,true,https://tgadsspy.com/niches/trading,https://tgadsspy.com/niches/trading/rss.xml
...
GET/api/v1/geos— List geos with counts

Countries we have classified creatives for, based on CTA URL TLD and language hints. Sorted by creative count descending.

cURL

curl https://tgadsspy.com/api/v1/geos

Node

const r = await fetch('https://tgadsspy.com/api/v1/geos')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/geos')
print(r.json())

Response

{
  "data": [
    { "code": "RU", "count": 4 },
    { "code": "IT", "count": 1 }
  ],
  "meta": { "total": 2 }
}
GET/api/v1/geos.csv— Geo distribution — CSV mirror

5-column CSV mirror of /api/v1/geos (code, name, count, intent_count, profile_url). Dual-signal pattern: count = audience-delivery (regional observer pool — internal volunteer network) vs intent_count = advertiser intent (creative content-derived: TLD + script + language). Researcher-friendly format for academic geographic ad-market studies. Public, no auth, 300s cache.

cURL

curl "https://tgadsspy.com/api/v1/geos.csv" > geos.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/geos.csv')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/geos.csv')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

code,name,count,intent_count,profile_url
RU,Russia,12450,8900,https://tgadsspy.com/countries/ru
TR,Türkiye,5200,3100,https://tgadsspy.com/countries/tr
IN,India,4100,2400,https://tgadsspy.com/countries/in
...
GET/api/v1/comparisons— List vs-pages (pairs, trios, niche-pairs, geo-pairs)

Programmatic access to all Wave-78/79 comparison pages. type=advertiser-pair returns 2-way brand comparisons (e.g. ftmo-vs-myfundedfx); type=advertiser-trio returns 3-way trifecta (top-3 per niche); type=niche-pair returns niche-vs-niche taxonomy pages (e.g. crypto-vs-gambling); type=geo-pair returns country-vs-country market pages (e.g. us-vs-de). Optional filters: ?niche=crypto (restrict by niche), ?advertiser=ftmo (find comparisons containing this advertiser), ?locale=ru (translate niche labels). Backed by 10-min Redis cache (same data as sitemap.xml).

ParamTypeDescription
typeadvertiser-pair|advertiser-trio|niche-pair|geo-pairComparison kind. Default advertiser-pair.
limitint 1–1001-100 entries. Default 50.
nichestring (niche slug)For advertiser-pair/trio: filter by primary niche. For niche-pair: pairs containing this niche.
advertiserstring (advertiser slug)For advertiser-pair/trio: returns only entries containing this advertiser.
localeen|ru|uk|it|es|pt|de|fr|ar|idLocale for label rendering. Default en.

cURL

curl "https://tgadsspy.com/api/v1/comparisons?type=advertiser-pair&niche=prop-firm&advertiser=ftmo&limit=5"

Node

const r = await fetch('https://tgadsspy.com/api/v1/comparisons?type=advertiser-pair&niche=prop-firm&advertiser=ftmo&limit=5')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/comparisons?type=advertiser-pair&niche=prop-firm&advertiser=ftmo&limit=5')
print(r.json())

Response

{
  "data": [
    {
      "type": "advertiser-pair",
      "canonical": "ftmo-vs-myfundedfx",
      "members": [
        { "slug": "ftmo", "name": "FTMO" },
        { "slug": "myfundedfx", "name": "MyFundedFX" }
      ],
      "niche": "prop-firm",
      "url": "https://tgadsspy.com/advertisers/vs/ftmo-vs-myfundedfx"
    }
  ],
  "meta": {
    "type": "advertiser-pair",
    "total": 5,
    "limit": 5,
    "locale": "en",
    "filters": { "niche": "prop-firm", "advertiser": "ftmo" },
    "plan": "FREE"
  }
}
GET/api/v1/comparisons/stats— Vs-vertical meta-stats (totals + top entities)

Single endpoint для dashboard headline tiles. Returns total comparison count per kind, top-10 advertisers by appearance в pairs/trios, top-10 niches by combined appearance, top-10 countries by geo-pair appearance. Cheap (reads cached pools — 1-2 batch Advertiser query). 5-min cache.

cURL

curl https://tgadsspy.com/api/v1/comparisons/stats

Node

const r = await fetch('https://tgadsspy.com/api/v1/comparisons/stats')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/comparisons/stats')
print(r.json())

Response

{
  "data": {
    "totals": {
      "advertiser-pair": 100,
      "advertiser-trio": 28,
      "niche-pair": 47,
      "geo-pair": 35,
      "all": 210
    },
    "topAdvertisers": [
      { "slug": "ftmo", "name": "FTMO", "pairCount": 8, "trioCount": 3, "total": 11 },
      ...
    ],
    "topNiches": [
      { "slug": "prop-firm", "label": "Prop firm", "nichePairCount": 4, "advertiserContextCount": 24, "total": 28 },
      ...
    ],
    "topCountries": [
      { "iso": "US", "name": "United States", "pairCount": 14 },
      ...
    ],
    "generatedAt": "2026-05-18T..."
  },
  "meta": { "plan": "FREE" }
}
GET/api/v1/comparisons/:type/:canonical— Vs-page deep metrics (full payload)

Companion к list endpoint — returns same data структура что vs-page renders (advertiser/niche/country metadata + creative counts + 90d advertiser counts + overlap arrays). 404 если pair fails filter rules (same gate as page). 5-min cache.

ParamTypeDescription
typeadvertiser-pair|advertiser-trio|niche-pair|geo-pairPath segment, required.
canonicalstringLex-sorted slug. Non-canonical orderings return 404 (no implicit redirect on API).

cURL

curl https://tgadsspy.com/api/v1/comparisons/advertiser-pair/ftmo-vs-myfundedfx

Node

const r = await fetch('https://tgadsspy.com/api/v1/comparisons/advertiser-pair/ftmo-vs-myfundedfx')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/comparisons/advertiser-pair/ftmo-vs-myfundedfx')
print(r.json())

Response

{
  "data": {
    "type": "advertiser-pair",
    "canonical": "ftmo-vs-myfundedfx",
    "url": "https://tgadsspy.com/advertisers/vs/ftmo-vs-myfundedfx",
    "advertisers": [
      {
        "slug": "ftmo",
        "name": "FTMO",
        "domain": "ftmo.com",
        "creativeCount": 248,
        "firstSeenAt": "2024-09-15T...",
        "lastSeenAt": "2026-05-17T...",
        "topNiche": "prop-firm"
      },
      { "slug": "myfundedfx", "name": "MyFundedFX", ... }
    ],
    "niche": "prop-firm"
  },
  "meta": { "type": "advertiser-pair", "canonical": "ftmo-vs-myfundedfx", "plan": "FREE" }
}
GET/api/v1/comparisons/related/:type/:canonical— Related vs-pages (recommendation engine)

Finds related comparisons sharing 1+ entity. advertiser-pair returns other pairs sharing a brand + 3-way trios containing a brand; advertiser-trio returns its 3 direct pairs + sibling trios; niche-pair/geo-pair return other pairs sharing one half. Useful for "you might also like" UIs and dashboard recommendations. 10-min cache.

ParamTypeDescription
typeadvertiser-pair|advertiser-trio|niche-pair|geo-pairPath segment, required.
canonicalstringLex-sorted slug.
limitint 1–20Default 10.

cURL

curl "https://tgadsspy.com/api/v1/comparisons/related/advertiser-pair/ftmo-vs-myfundedfx?limit=5"

Node

const r = await fetch('https://tgadsspy.com/api/v1/comparisons/related/advertiser-pair/ftmo-vs-myfundedfx?limit=5')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/comparisons/related/advertiser-pair/ftmo-vs-myfundedfx?limit=5')
print(r.json())

Response

{
  "data": [
    {
      "type": "advertiser-pair",
      "canonical": "ftmo-vs-fundednext",
      "members": [{"slug":"ftmo","name":"FTMO"}, {"slug":"fundednext","name":"FundedNext"}],
      "niche": "prop-firm",
      "url": "https://tgadsspy.com/advertisers/vs/ftmo-vs-fundednext"
    },
    {
      "type": "advertiser-trio",
      "canonical": "ftmo-vs-fundednext-vs-myfundedfx",
      "members": [...3 advertisers],
      "niche": "prop-firm",
      "url": "https://tgadsspy.com/advertisers/vs/ftmo-vs-fundednext-vs-myfundedfx"
    }
  ],
  "meta": { "type":"advertiser-pair", "canonical":"ftmo-vs-myfundedfx", "total":5, "plan":"FREE" }
}
GET/api/v1/comparisons.csv— Vs-pages — CSV mirror (researcher-friendly)

10-column CSV mirror of /api/v1/comparisons. Default type=all combines all 4 kinds в один dataset (researcher cross-cut analysis). Same ?niche= и ?advertiser= filters как JSON sister (filter applied post-fetch с pool widening). Empty member_3_* для pair/niche-pair/geo-pair (только trio has 3 members). OWASP formula-injection escaped. Public, no auth, 60s cache.

ParamTypeDescription
typeadvertiser-pair|advertiser-trio|niche-pair|geo-pair|allDefault all (combines all 4 kinds).
limitint 1–100Per-kind cap. Default 50.
nichestringFor advertiser-*: Advertiser.primaryNiche filter. For niche-pair: pairs containing this slug.
advertiserstringFor advertiser-pair/trio: returns rows containing this slug.

cURL

curl "https://tgadsspy.com/api/v1/comparisons.csv?type=all&limit=50" > comparisons.csv

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/comparisons.csv?type=all&limit=50')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/comparisons.csv?type=all&limit=50')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

type,canonical,member_1_slug,member_1_name,member_2_slug,member_2_name,member_3_slug,member_3_name,niche,url
advertiser-pair,ftmo-vs-myfundedfx,ftmo,FTMO,myfundedfx,MyFundedFX,,,prop-firm,https://tgadsspy.com/advertisers/vs/ftmo-vs-myfundedfx
advertiser-trio,ftmo-vs-fundednext-vs-myfundedfx,ftmo,FTMO,fundednext,FundedNext,myfundedfx,MyFundedFX,prop-firm,https://tgadsspy.com/advertisers/vs/ftmo-vs-fundednext-vs-myfundedfx
niche-pair,crypto-vs-gambling,crypto,Crypto,gambling,Gambling,,,,https://tgadsspy.com/niches/vs/crypto-vs-gambling
geo-pair,de-vs-us,de,Germany,us,United States,,,,https://tgadsspy.com/countries/vs/de-vs-us
...
GET/api/v1/trends— Time series — creatives per day

New creatives counted per UTC day, pivoted on a dimension. Useful for charts of niche growth, category mix, payment-source split or geo breakdown over time. dim=category aggregates niches into 6 super-groups (Finance/Gambling/Tech/Content/Commerce/Lifestyle).

ParamTypeDescription
dimniche|category|source|geoWhat to group by. Default niche. category aggregates niches into 6 super-groups.
daysint 1–90Lookback window. Default 30.

cURL

curl "https://tgadsspy.com/api/v1/trends?dim=niche&days=30"

Node

const r = await fetch('https://tgadsspy.com/api/v1/trends?dim=niche&days=30')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/trends?dim=niche&days=30')
print(r.json())

Response

{
  "data": [
    { "date": "2026-04-19", "series": { "crypto": 8, "trading": 4, "vpn": 2 } },
    { "date": "2026-04-20", "series": { "crypto": 10, "trading": 3 } }
  ],
  "meta": {
    "dim": "niche",
    "days": 30,
    "since": "2026-03-20T00:00:00Z",
    "keys": ["crypto","trading","vpn"],
    "totals": { "crypto": 18, "trading": 7, "vpn": 2 }
  }
}
GET/api/v1/analytics— Analytics catalog (machine-readable)

Index endpoint listing all analytics surfaces with path/method/summary/params/csvMirror/plans/status. Useful for SDK / dashboard builders that auto-discover capabilities. No auth required.

ParamTypeDescription

cURL

curl "https://tgadsspy.com/api/v1/analytics" | jq '.endpoints[] | select(.status == "live") | .path'

Node

const r = await fetch('https://tgadsspy.com/api/v1/analytics')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics')
print(r.json())

Response

{
  "endpoints": [
    {
      "path": "/api/v1/analytics/share-of-voice",
      "method": "GET",
      "summary": "...",
      "params": ["niche", "geo", "top", "from", "to"],
      "csvMirror": "/api/v1/analytics/share-of-voice.csv",
      "plans": ["FREE", "PRO", "ENTERPRISE"],
      "status": "live"
    },
    ...
  ],
  "meta": {
    "version": "phase-2",
    "totalEndpoints": 15,
    "liveEndpoints": 12,
    "stubEndpoints": 3,
    "csvMirrors": 12,
    "specUrl": "/api/v1/openapi.json",
    "docsUrl": "/api-docs"
  }
}
GET/api/v1/feeds— Feeds catalog (single discovery anchor)

Machine-readable catalog of all 22+ data feeds and datasets. Each entry has structured metadata: format (json/csv/xml/feed+json/rss+xml/opensearch/text), plan (ANON/FREE/PRO/ENTERPRISE), cache_ttl_sec, auth_required, license, tags array, schema_url. SDK builders use this as single discovery anchor вместо scraping data_feeds blocks across /api/product and /api/v1/ecosystem. Filterable.

ParamTypeDescription
formatstringjson | csv | xml | feed+json | rss+xml | opensearch | text
planstringANON | FREE | PRO | ENTERPRISE
tagstringcashier, miniapps, glossary, ecosystem, researcher, sdk, ai-crawler, …

cURL

curl "https://tgadsspy.com/api/v1/feeds?format=csv&plan=FREE" | jq '.data[].url'

Node

const r = await fetch('https://tgadsspy.com/api/v1/feeds?format=csv&plan=FREE')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/feeds?format=csv&plan=FREE')
print(r.json())

Response

{
  "data": [
    {
      "id": "api-v1-cashier-creatives-csv",
      "name": "Cashier Creatives — CSV",
      "url": "https://tgadsspy.com/api/v1/cashier-creatives.csv",
      "format": "csv",
      "description": "27-column CSV export...",
      "plan": "FREE",
      "cache_ttl_sec": 60,
      "auth_required": true,
      "license": "CC-BY-4.0",
      "tags": ["cashier", "creatives", "csv", "researcher"]
    }
  ],
  "meta": {
    "total": 8,
    "total_unfiltered": 22,
    "by_format": { "csv": 4, "json": 14, "..." },
    "by_plan": { "ANON": 17, "FREE": 5 },
    "by_tag": { "cashier": 4, "researcher": 4, "..." },
    "filters_applied": { "format": "csv", "plan": "FREE", "tag": null }
  }
}
GET/api/v1/analytics/* (Phase 2)— Analytics endpoints — Phase 2 (10 endpoints, 7 with real compute)

Pro+ analytics surface. Phase 1 endpoints (real compute): /share-of-voice (SoV by advertiser in niche), /creative-fatigue (peak detection + fatigueIndex per creative), /frequency-distribution (imps/unique-channel histogram + p50/p90), /competitor-overlap (Jaccard half-matrix for 2-5 advertisers across channels/niches/creatives), /spend-estimate (groupBy advertiser/niche/geo with confidence band). Phase 2 endpoints (real compute): /geo-snapshot (top advertisers/niches per geo + growthVsPrior), /niche-leaderboard (rank by impressions/newCreatives/sov/spend with delta), /advertiser-timeline (per-period creatives+impressions, day/week/month granularity), /niche-pricing (proxy CPM percentiles 25/50/75), /advertiser-creatives (cursor pagination + top-regions per creative), /channel-ad-load (channel-owner perspective: total/uniqueAdvertisers/daily/estCpmRange), /cta-domains (top CTA hosts per advertiser/niche with isAffiliate/isShortener heuristics). Stubs (require async-job infra): /exports POST + /exports/<jobId> GET (sync CSV mirrors below cover typical use), /diff-webhook POST (subscribe to advertiser change events). Plan-gating: ANON 401, FREE narrow window/top, PRO/ENTERPRISE full access.

ParamTypeDescription
(varies per endpoint)see specEach endpoint has its own zod schema. Common parameters: from/to (ISO-8601 date, default last 30d / 90d), niche, geo (alpha-2 ISO), advertiser (slug). See outputs/specs/analytics-phase-2-spec.md in repo.

cURL

curl -H "X-Api-Key: $KEY" "https://tgadsspy.com/api/v1/analytics/share-of-voice?niche=crypto&top=5"

Node

const r = await fetch('https://tgadsspy.com/api/v1/analytics/share-of-voice?niche=crypto&top=5')
const data = await r.json()

export const dynamic = 'force-dynamic'
console.log(data)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/share-of-voice?niche=crypto&top=5')
print(r.json())

Response

{
  "data": { "totalImpressions": 1240000, "top": [...], "otherSov": 0.18 },
  "meta": { "plan": "PRO" }
}
GET/api/v1/analytics/advertiser-creatives.csv— Export advertiser creatives as CSV (Pro+)

Same filters as JSON sibling but flat (no cursor) — up to 500 rows in one shot. 21 columns including ctaHost (for affiliate/shortener analysis), reachEstimate, spendEstimate, daysAlive, permalink. Attachment download. Pro+ only (FREE blocked).

ParamTypeDescription
advertiserstringRequired. Advertiser slug.
regionISO-3166-1 alpha-2Filter by impressions region.
nichestringFilter by creative niche.
fromISO-8601Default 90 days ago.
toISO-8601Default now.
limitint 1–500Default 500.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/advertiser-creatives.csv?advertiser=tg-mrp_tradingbot&limit=200"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/advertiser-creatives.csv?advertiser=tg-mrp_tradingbot&limit=200')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/advertiser-creatives.csv?advertiser=tg-mrp_tradingbot&limit=200')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary; see Content-Disposition header for filename)
GET/api/v1/analytics/niche-leaderboard.csv— Export niche leaderboard as CSV

Top advertisers in a niche with rank, metric, delta vs prior window, newCreatives. 8 columns. FREE: only impressions/newCreatives ranking; spend/sov ranking is Pro+.

ParamTypeDescription
nichestringRequired. Niche slug.
geoISO-3166-1 alpha-2Optional geo filter.
rankByimpressions|sov|newCreatives|spendDefault impressions. spend/sov require Pro+.
topint 1–50Default 20. FREE caps at 20.
fromISO-8601Default 30 days ago.
toISO-8601Default now.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/niche-leaderboard.csv?niche=crypto&rankBy=impressions&top=20"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/niche-leaderboard.csv?niche=crypto&rankBy=impressions&top=20')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/niche-leaderboard.csv?niche=crypto&rankBy=impressions&top=20')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/spend-estimate.csv— Export spend estimates as CSV

GroupBy advertiser/niche/geo with USD ranges and confidence band. 7 columns. FREE caps window 7d / limit 10. Estimate based on observed impressions × niche-level CPM ±25% confidence.

ParamTypeDescription
groupByadvertiser|niche|geoRequired. Aggregation key.
fromISO-8601Required. Window start.
toISO-8601Required. Window end. Hard cap 365d.
nichestringFilter to a single niche.
geoISO-3166-1 alpha-2Filter to a single geo.
limitint 1–200Default 50.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/spend-estimate.csv?groupBy=advertiser&niche=crypto&from=2026-04-01&to=2026-04-30"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/spend-estimate.csv?groupBy=advertiser&niche=crypto&from=2026-04-01&to=2026-04-30')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/spend-estimate.csv?groupBy=advertiser&niche=crypto&from=2026-04-01&to=2026-04-30')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/geo-snapshot.csv— Export geo snapshot as CSV

Long format: top advertisers + top niches in one CSV. 5 columns (kind=advertiser|niche, rank, slug, name, impressions). Filter by 30-day default window.

ParamTypeDescription
geoISO-3166-1 alpha-2Required. Geo code (e.g. US, BR, KZ).
fromISO-8601Default 30 days ago.
toISO-8601Default now.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/geo-snapshot.csv?geo=KZ"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/geo-snapshot.csv?geo=KZ')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/geo-snapshot.csv?geo=KZ')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary; first half rows kind=advertiser, second half kind=niche)
GET/api/v1/analytics/advertiser-timeline.csv— Export advertiser timeline as CSV

Per-period creatives + impressions for one advertiser. 3 columns (period, creatives, impressions). Granularity day | week | month — period format ISO-date / YYYY-WW / YYYY-MM accordingly.

ParamTypeDescription
advertiserstringRequired. Advertiser slug.
granularityday|week|monthDefault day.
fromISO-8601Default 90 days ago.
toISO-8601Default now.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/advertiser-timeline.csv?advertiser=tg-mrp_tradingbot&granularity=week"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/advertiser-timeline.csv?advertiser=tg-mrp_tradingbot&granularity=week')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/advertiser-timeline.csv?advertiser=tg-mrp_tradingbot&granularity=week')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/niche-pricing.csv— Export niche pricing percentiles as CSV

Proxy CPM percentiles 25/50/75 per niche × geo, with observed-creatives count and confidence band. 7 columns. Method = observed impressions ÷ channel-members × 1000.

ParamTypeDescription
nichestringOptional niche filter (omit for all).
geoISO-3166-1 alpha-2Optional geo filter.
topint 1–50Default 20.
fromISO-8601Default 7 days ago.
toISO-8601Default now.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/niche-pricing.csv?niche=crypto"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/niche-pricing.csv?niche=crypto')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/niche-pricing.csv?niche=crypto')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/channel-ad-load.csv— Export channel ad-load as CSV

Long format: top advertisers (kind=advertiser) + daily series (kind=daily) for one channel. 4 columns (kind, key, name, creatives). Channel-owner perspective: how much ad-load you carry.

ParamTypeDescription
channelUsernamestringRequired. Channel username (no @).
fromISO-8601Default 30 days ago.
toISO-8601Default now.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/channel-ad-load.csv?channelUsername=durov"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/channel-ad-load.csv?channelUsername=durov')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/channel-ad-load.csv?channelUsername=durov')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/cta-domains.csv— Export CTA-domain distribution as CSV

Top CTA hosts per advertiser or niche, with isAffiliate / isShortener heuristic flags. 6 columns. Either advertiser OR niche is required.

ParamTypeDescription
advertiserstringAdvertiser slug (either this or niche required).
nichestringNiche slug (either this or advertiser required).
topint 1–50Default 20.
fromISO-8601Default 30 days ago.
toISO-8601Default now.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/cta-domains.csv?advertiser=tg-mrp_tradingbot"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/cta-domains.csv?advertiser=tg-mrp_tradingbot')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/cta-domains.csv?advertiser=tg-mrp_tradingbot')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/share-of-voice.csv— Export share-of-voice as CSV

Top advertisers in a niche/geo by impressions, with sov fraction. 5 columns (rank, advertiserSlug, advertiserName, impressions, sov). FREE: top ≤ 10; Pro+: top ≤ 50.

ParamTypeDescription
nichestringEither niche or geo required.
geoISO-3166-1 alpha-2Either niche or geo required.
topint 1–50Default 10.
fromISO-8601Window start.
toISO-8601Window end.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/share-of-voice.csv?niche=crypto&top=20"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/share-of-voice.csv?niche=crypto&top=20')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/share-of-voice.csv?niche=crypto&top=20')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/creative-fatigue.csv— Export creative-fatigue summary as CSV

Per-creative summary (full daily series omitted — use JSON endpoint for that). 8 columns (creativeId, title, firstSeenAt, daysAlive, peakDay, fatigueIndex, status, permalink). Status enum: ramping | peak | fatigued | paused.

ParamTypeDescription
advertiserstringFilter by advertiser slug.
nichestringFilter by niche slug.
creativeIdstringSingle creative ID.
fromISO-8601Window start.
toISO-8601Window end.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/creative-fatigue.csv?advertiser=tg-mrp_tradingbot"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/creative-fatigue.csv?advertiser=tg-mrp_tradingbot')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/creative-fatigue.csv?advertiser=tg-mrp_tradingbot')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)
GET/api/v1/analytics/frequency-distribution.csv— Export frequency-distribution histogram as CSV

Imps/unique-channel histogram with summary stats. 3 columns (bucketLow, bucketHigh, creatives). Trailing rows: bucketLow=-1 → total, -2 → median, -3 → p90 (sentinel encoding).

ParamTypeDescription
advertiserstringFilter by advertiser slug.
nichestringFilter by niche slug.
binsint 5–20Histogram bin count. Default 10.
fromISO-8601Window start.
toISO-8601Window end.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/frequency-distribution.csv?niche=crypto&bins=15"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/frequency-distribution.csv?niche=crypto&bins=15')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/frequency-distribution.csv?niche=crypto&bins=15')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary; first line is # comment documenting sentinels)
GET/api/v1/analytics/competitor-overlap.csv— Export competitor-overlap matrix as CSV

Long format: advertiser set sizes (kind=set) + Jaccard pair matrix (kind=pair). 8 columns (kind, a, b, jaccard, intersection, union, setSize, name). 2-5 advertisers, metric = channels | niches | creatives.

ParamTypeDescription
advertiserscsv-list 2-5Required. Comma-separated advertiser slugs.
metricchannels|niches|creativesDefault channels.
fromISO-8601Window start.
toISO-8601Window end.

cURL

curl -H "X-Api-Key: $KEY" -O "https://tgadsspy.com/api/v1/analytics/competitor-overlap.csv?advertisers=acme,corp,foo&metric=niches"

Node

import { writeFile } from 'node:fs/promises'

const r = await fetch('https://tgadsspy.com/api/v1/analytics/competitor-overlap.csv?advertisers=acme,corp,foo&metric=niches')
const csv = await r.text()
await writeFile('ads.csv', csv)

Python

import requests

r = requests.get('https://tgadsspy.com/api/v1/analytics/competitor-overlap.csv?advertisers=acme,corp,foo&metric=niches')
with open('ads.csv', 'wb') as f:
    f.write(r.content)

Response

(text/csv binary)

Roadmap

  • Webhooks for alert.fired (Business only).
  • GET /api/v1/creatives/:id and related lookup endpoints.
  • Historical series for reach and CPM estimates.
  • Business-tier 60 000 req/min + team seats + SLA.

Want a feature prioritised? contact us.