On this page

E-commerce data API documentation

The SellWinners API gives you e-commerce and advertising intelligence over HTTPS with JSON responses: Shopify stores with their products and traffic; store products with their price, sales estimates, reviews and ads; Meta, Google and TikTok ads; advertisers; and the emails brands send. Every endpoint is also available to AI agents through our hosted MCP server. This page covers authentication, the response format, pagination, sorting and filters, rate limits and credits, errors and media URLs, then every endpoint with its parameters and an example request, and the MCP server's tools.

Base URL
https://api.sellwinners.com
Try it live

Send real requests from the Playground on paid plans, or generate a client from the OpenAPI spec:

https://api.sellwinners.com/openapi.json

Quickstart

  1. Create an account, confirm your email and choose a paid plan: the API and the MCP server start there.
  2. Open API keys and create a key. Copy it right away: it's shown only once.
  3. Make your first request:
curl "https://api.sellwinners.com/v1/lookup?q=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

Authentication

Send your API key on every request in the X-API-Key header, or as a bearer token:

X-API-Key: YOUR_API_KEY
# or
Authorization: Bearer YOUR_API_KEY

Keys start with ak_live_. Keep them secret: don't put them in front-end code or public repositories. You can create several keys (one per app or environment) and revoke any key from your dashboard; a revoked key stops working immediately.

Responses

Every response is JSON. It carries a requestId and the result under data: a list for searches and listings, one object for a single record. Lists add a pagination object, and some answers add meta.

{
  "requestId": "req_8f2c1a9b4d7e6f3a2b1c0d9e",
  "data": [
    {
      "id": "facebook_1203948571620394",
      "platform": "facebook",
      "status": "active",
      "daysRunning": 42,
      "media": { "type": "video", "thumbnailUrl": "https://api.sellwinners.com/v1/media/file/b7a0.jpg", "mediaUrl": "https://api.sellwinners.com/v1/media/file/4c1e.mp4" },
      "advertiser": { "id": "104958372615", "name": "Glow Labs", "liveAdsCount": 86 },
      "content": { "title": "Glass skin in 14 days", "body": "Dermatologist tested.", "callToAction": "Shop now", "landingPageUrl": "https://glowlabs.example/serum" },
      "metrics": { "reach": 184000, "estimatedSpend": 1656, "duplicates": 3 },
      "audience": { "targetedCountries": ["FR", "DE"], "mainCountry": "FR" },
      "rank": { "currentRank": 4, "rankDelta": -2, "improvementPct": 0.3333 },
      "flags": { "isEuAd": true },
      "extra": { "shop": { "domain": "glowlabs.example" } }
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1840, "totalPages": 74, "hasMore": true }
}

Records are nested objects: an ad has media, advertiser, content, metrics, audience, rank and flags, and shops, advertisers, Google ads, TikTok items and emails are grouped the same way. A value that is not known is null. Further fields with no fixed place are kept under extra. The example above is shortened.

In an ad, content.title is the headline and content.callToAction is readable text such as "Shop now". metrics.estimatedSpend is the source's spend estimate when it has one (a single ad from /v1/ads/{adId} reads it), otherwise reach x 9 / 1000 (9 USD per 1,000 people reached); a spend estimate keeps two decimals under 10 USD and is in whole dollars from 10 USD up. rank.rankDelta is the current rank minus the previous one, so a negative value means the ad moved up, and rank.improvementPct is a fraction (0.25 is a quarter).

The brand tracker rank reports (/ad-rank, /scaling-ads, /v1/workspace/scaling-ads and the MCP tool get_brandtracker_scaling_ads) add their own metrics: there metrics.rankDelta is the previous rank minus the current one (positive: places gained) and metrics.improvementPct is the fraction of the previous rank gained, as in an ad (0.875 is 87.5%). On a single ad, metrics.reachDelta1d, reachDelta7d and reachDelta30d are filled from its reach history. Shops name their categories: catalog.mainCategory in listings, plus catalog.categories on a single shop.

In a Google ad, media.type and media.format are text, image or video, and media.url is the ad's image: for a video ad, its thumbnail (there is no video file). transparencyUrl is the ad on Google's Ads Transparency Center, where a video ad plays; it is null when the ad has no Google ids. network is search, youtube, shopping, maps or other, and so are the values of extra.networks.

Changed on October 19, 2026:

  • A Google ad's media.format was a format code and is now text, image or video, its media.type can be text or video, and extra.networks uses the lower-case names of network.
  • A Google media.url is never a video file, even when media.type is video.
  • In the Google formats filter, image now means image ads (it meant text ads before), so use text for text ads. The earlier codes static_image, html5_iframe and responsive_display, and their short names, are still accepted.

A Google ad's status is active only while Google shows the ad: one Google has not shown for more than 7 days is unknown. daysRunning counts the days from firstSeenAt to lastSeenAt, both included; extra.servedDays is the data source's own count, which goes on after an ad stops. The filters agree with what each ad shows: status=active keeps the ads Google showed in the last 7 days and status=inactive the ads the data source marks stopped, so an unknown ad is under neither; minDaysRunning and maxDaysRunning the ads whose daysRunning is in range. Such a list has pagination.total null, and when few of the ads read match it ends early, with meta.partial and a warning.

With no search text, sortBy=relevance lists the newest; sortBy=reach takes order=desc only. With status=active, sortBy=reach lists few ads: in reach order the first ads are mostly ones Google stopped showing, so sort by newest for the ads Google shows now (its warning says so). Google ads take no sortBy=longestRunning: the data source ranks it by days that go on after an ad stops, so it listed ads Google no longer shows, and it answers 400 with that reason.

extra.startIsFloor marks an ad first seen on May 31, 2018, the first day of Google's ad data, so it may be older. audience.countries lists every audience country, with a percentage only for an ad shown in one; remarketing and interest are null when unknown.

Google reports a reach for some of the ads shown in the EU only, often only as 10,000,000, the top of its scale (10 million or more): most ads have none, and nullReasons says why reach.value is null (not_reported: an ad shown in the EU that Google reports none for; eu_only: an ad shown elsewhere), except for a reach the plan leaves out. extra.networks is the data source's list of the ad's platforms, which may not name network. extra.shop.google holds the Google totals of the advertiser's website; for a site that is not a shop (an app store, a social site, a link shortener) advertiser.domain and websiteId are null.

Changed on October 20, 2026:

  • A domain (GET /v1/shops/{domain}, the lookup, a TikTok domain, the competitor brief) is the site with exactly that domain, also outside the shop index; one the data source does not reach answers 404.
  • GET /v1/lookup ranks results best first: a domain's own site, its own Facebook pages (main page first), then the pages named like it; for a name, the brand's own site and its own pages (main page first), then the shops and pages found by the name.
  • With the brand's site found, a shop or page that has the name only inside a word is left out and a site of that name is exact only when it runs ads; otherwise a name match is exact only with traffic or ads. Official pages of another name with no live ad come after the pages found by name.
  • A shop row's signals.activeAdsSource says where its activeAds come from: page (its main page's live ads, read now, on the shop's own row) or index (the shop index's count, which can be older).
  • A shop domain search (searchType=domain) lists the exact site first, with extra.exactDomainMatch (and extra.inShopIndex false when the shop index leaves it out).
  • For a site that is not a shop (an app store, a social or messaging site, a link shortener or a tracking redirect), an advertiser row's extra.domain is null, an advertiser record names it in extra.nonShopSite, leaves out extra.platforms and takes linkedShops from its landing pages (fromLandingPages), and an ad has no shops.
  • Date-times the data source sends without a zone are UTC and are now sent with +00:00.
  • In email stats, emailsByDayOfWeek is keyed by the day's number: 0 is Sunday, 6 Saturday.
  • Lookup rows may carry nullReasons, and a shop record meta.partial when its listing figures could not be read.

Also changed on October 20, 2026 (TikTok):

  • A TikTok item's publishedAt is UTC. It was 1 or 2 hours late, so a post made in the last hours of a UTC day showed the next day and a daysRunning one day short.
  • The filters agree with it: publishedAfter and publishedBefore are UTC (a date alone is the start of its day, and publishedBefore lists the posts before it), minDaysRunning and maxDaysRunning count from the UTC day, as daysRunning does, and sortBy=longestRunning starts at August 31, 2016, 22:00 UTC.

Also changed on October 20, 2026 (Google ads):

  • GET /v1/google-ads, POST /v1/google-ads/query and the MCP tool take no sortBy=longestRunning (nor daysRunning) and answer 400 with the reason: the data source ranks it by days that go on after an ad stops, so it listed ads Google no longer shows.
  • A Free search whose first results status=active leaves short answers meta.partial with a warning that says how many of the ads read it lists.
  • In extra.shop, a site with no traffic data has no monthlyVisits (it was 0), a trafficGrowth30d comes only beside visits above 0, and extra.shop.google leaves out a 0 totalReach or weeklyReach (never reported) and, when it counts no ad, the 0 counts.
  • A Google ad saved to a board reads the same.

Also changed on October 20, 2026 (shops):

  • In GET /v1/shops/{shopId}, advertising.summary.reach30d is the EU reach of the last 30 days, summed by date (it was the total since tracking began, now totalReach), spend30d is that reach x 9 / 1000, extra.estimatedSpendUsd is the spend since tracking began and extra.adsLaunched30d sums the ads launched in the last 30 days; all are null for a shop with no EU or UK reach.
  • Shop records, listed shops and email stats carry nullReasons, a field path mapped to why it is null: not_shopify (sales and products are estimated for Shopify stores only), no_estimate, not_measured, eu_uk_only, not_linked (no TikTok profile), not_on_tp, no_reviews, none_found.
  • A sales estimate of zero next to units sold is null, in records, listings and the sales history, whose period=week has one point per week.
  • traffic.growth30d is a fraction (-0.1543 is -15.4%), and traffic.history starts at the first month with visits.
  • catalog.mainCategory comes from the category ids (the most specific of the main branch), with catalog.categoryLeaves and productsCountCapped (25,001 is the data source's ceiling: 25,000 or more).
  • A Trustpilot page with no review has a null rating.
  • tiktok.matchedBy is socials or handle when the TikTok figures come from the shop's social profiles or from a profile found by its handle (a match, not a link of the data source).
  • advertising.mainPageActiveAds is the main page's live ads (its ad overview's reading, as its Main page in linkedAdvertisers shows it; the count shop lists show only without one) and linkedAdvertisers[].rank the page's rank.
  • Similar shops leave out the shop itself and its own sites, and each page is filled from further down the list (offset and limit count the list without them).
  • Products sorted by popularity rank the shop's best sellers first (meta.order).
  • A shop's emails and email stats count every campaign type, and their 90-day figures are null when unknown.
  • A sales sort lists one row per Shopify store (extra.sharedSalesWith), and sortBy=estMonthlySales&order=asc leaves out the shops with no estimate.

Also changed on October 20, 2026 (shop figures):

  • A sales sort of GET /v1/shops reads on past the domains it merges into one row per Shopify store (it stopped after the first rows), merges a store's domains further down the list too, and its pagination.total is null until the list is read to its end; sortBy=estMonthlySales&order=asc starts at an estimate of 100 USD (minMonthlySales 100).
  • A sales estimate under 0.50 USD a unit sold is null (no_estimate), in records, listings and the sales history.
  • traffic.monthlyVisits is null for a site not measured yet and traffic.growth30d when the month before had no visits (not_measured); a social network's growth30d comes from its follower history when the data source gives 0 or none, and 0 followers is null (not_measured).
  • Listed shops say why catalog.productsCount and sales.unitsSold are null.
  • extra.storeWide marks a domain with 0 visits that carries its store's sales (a measured 0, or another domain of the store, named in extra.sharedSalesWith, has the visits; Free leaves the name out of a shop record).
  • advertising.mainPageActiveAds is the main page's live ads as its ad overview reads them (the count shop lists show only without one).
  • Similar shops also leave out the shop's brand stores, and extra.similarIndexed is false for a shop the similarity index does not hold.
  • catalog.mainCategory keeps the data source's own label only when it is a category's name.
  • A media file an answer linked that the data source no longer has answers 200 with an empty body and X-Media-Missing: true.

Also changed on October 20, 2026 (advertisers and Meta ads):

  • An advertiser's reach is EU and UK reach, the advertiser search's own windows: advertising.reach30d, extra.reach14d, reach90d and totalReach are null for a page with no EU or UK ads and no reach, or for a window the data source has not counted, and nullReasons says why (eu_uk_only, not_measured); a page created inside a window has all its reach in it (they were 0).
  • In GET /v1/advertisers/{advertiserId} the reach is the one advertiser lists show (it was read 30 readings back, and readings skip days), the spend estimates are null with it, extra.avgSpendUsd14d is the average daily spend of 14 days, extra.avgActiveAds14d is the 14-day average of its live ads (it was its new ads of 14 days), where the data source has not computed it, for a page created inside the 14 days from its live ads read since its first day (extra.averagedFrom), else null, and the new-ads counts of a page created inside the window count every one of its ads.
  • advertising.countryDistribution is the share of its live ads that target each country (an ad targets several), extra.reachCountries holds each country's share of the EU reach, extra.platforms.meta holds the page's own ads (it held the shop's main page's), a TikTok or Google count with no figure is left out, extra.mainLandingPages falls back on the preview of a new page's landing pages, and the lastAds of a page whose ads the ad search has not taken in yet are the latest ones its advertiser row lists, with meta.indexing, as on GET /v1/advertisers/{advertiser_id}/ads (with meta.liveAds).
  • New: GET /v1/advertisers/{advertiserId}/history, the page's live ads and the EU reach it gained, day by day.
  • An Instagram follower count of 0 is null (the data source writes 0 for a page with no account it knows).
  • A Meta ad's metrics.reach and its spend are null for an ad not shown in the EU or the UK (eu_uk_only; they were 0 or null) and for an EU ad whose reach is not counted yet (not_measured; it was 0), media rows saying why in nullReasons.reach, media.type is carousel for an ad of more than one image or video, and extra.startIsFloor marks an ad started on January 1, 2018, the first day of the data source's Meta ad dates.
  • sortBy=adRank lists the best rank (1) first, whatever the order.
  • One ad (GET /v1/ads/{adId}) takes the latest reach the data source reports and the spend of it, counts its reach deltas by date while its reach history is current (else they are null), lists its images and videos as its search row does, fills advertiser.reach30d and pageAnalytics.instagramFollowersHistory, adds pageAnalytics.reachHistory (the same series as impressionsHistory), and names a shop the record gives by its id only (its traffic null with nullReasons shops.traffic when the site is not measured); its audience.gender, ageMin, ageMax and metrics.aggregatedReach are always null, as the data source does not report them for one ad.
  • In an advertiser search, sortBy=reach ranks by the total reach since tracking began and newAds by the new ads of 14 days.
  • A Meta ad's targeting says why its reach is null: eu_uk_only only for an ad that targets no EU or UK country; one that targets one, or whose targeting is not known yet, is not_measured in its first 7 days and not_reported after (they were eu_uk_only), in ad listings, media rows and one ad.
  • One ad reads its reach and spend histories as one series, one reading a day (its deltas too), and takes that series' last reading and spend when the record's reach is more than twice it and the series runs to the ad's last day; its media falls back on its first listed file, and advertiser.totalReach on the page details' EU reach.
  • An advertiser record whose row reads no reach next to page details that read some has their reach (extra.totalReach, the spend of it, advertising.reach30d counted on it), its extra.reachCountries shares are never rounded to 0, extra.averagedFrom is never before the day the page was created, and its daily history (extra.history, GET /v1/advertisers/{advertiserId}/history) leaves out the readings the data source missed (a run of zeros of 14 days or fewer between readings above 0).
  • One ad that takes its series' reading keeps the record's reach in extra.recordReach (the figure ad listings show); in an advertiser search, a row that reads no EU reach next to page details that read some has their reach, as its record does; and GET /v1/advertisers/{advertiserId}/history keeps the readings of 0 of a page with no EU ad now that gained reach before the days asked (it gained none; they were left out as not_measured).
  • On Free, an ad whose reach is unknown says why as on paid plans; only a reach the plan leaves out has no reason.

Also changed on October 20, 2026 (spend estimates):

  • An estimated spend under 10 USD keeps two decimals: a reach of 140 at 9 USD per 1,000 people reached is 1.26 (it was 1), and a daily average keeps its own cents; from 10 USD up a spend estimate is in whole dollars (a reach of 2,000 is 18).
  • This holds for the advertiser record's extra.estimatedSpendUsd and extra.avgSpendUsd14d, a shop's advertising.summary.spend30d and extra.estimatedSpendUsd, a Meta ad's metrics.estimatedSpend, and a brand tracker's statistics.euData.estimatedSpend30d and the estimatedSpend of each /time-series point (both had two decimals at any amount), in the API and the MCP tools alike. Where the data source's own figure is that estimate in whole dollars, it keeps its cents the same way.

Also changed on October 20, 2026 (advertiser reach and daily history):

  • GET /v1/advertisers/{advertiserId} adds extra.reachScope: outside_eu_uk for a page most of whose reach by country was seen outside the EU and the UK (the data source reports the reach of some ads shown elsewhere too; its reach and the estimates made from it are then that reach, not EU reach), else eu_uk. Its extra.avgSpendUsd14d of a page created inside the 14 days is its spend over the whole days since it was created (one at least; it was its 14-day reach over 14 days where the advertiser row had one).
  • The advertiser record's extra.history and GET /v1/advertisers/{advertiserId}/history start on the day the page was created; extra.history.newAds leaves out its 0 of the days the data source missed, extra.followersHistory and an ad's pageAnalytics likes and followers a 0 between two readings above 0 or of such a day, and the daily spend estimates keep two decimals under 10 USD.
  • A page whose live ads no list holds yet has meta.indexing on its record, and an empty first page of GET /v1/advertisers/{advertiser_id}/ads with meta.indexing and meta.liveAds.
  • One ad (GET /v1/ads/{adId}): extra.spendHistory starts on the day the ad started, each spendUsd with two decimals under 10 USD; advertiser.totalReach is never below the last reading of pageAnalytics.reachHistory (extra.pageRecordReach then holds the record's total, the one advertiser lists show); extra.recordSpend is the spend of extra.recordReach; extra.reachScope and extra.pageReachScope say where most of the ad's reach and of its page's was seen.

Also changed on October 20, 2026 (brand trackers):

  • In GET /v1/brandtrackers and GET /v1/brandtrackers/{id}, a 0 of advertising.newAdsLastDay beside launches in the last 7 days is checked against the shop's launches of yesterday: their count, or null (not_measured) with no reading of that day; a listing checks 20 brands a call at most, those of the page asked for.
  • In /top-ads and /v1/workspace/top-ads, metrics.totalReach is the ad's EU reach: null for an ad shown outside the EU and the UK (eu_uk_only) or an EU ad not counted yet (not_measured), with nullReasons, and last in a reach sort (it was 0).
  • /testing counts its reach stats over the ads whose reach is known, with nullReasons stats.reach for a batch with none.
  • In /hooks, /transcripts, /landing-pages and the workspace hooks and landing pages, a totalImpressions of 0 is null with the new reason no_eu_reach (no EU or UK reach counted for its ads; not_measured with euOnly), last in its sort.
  • In /ad-rank, /scaling-ads and /v1/workspace/scaling-ads, where an ad's rank history starts inside a 14 or 30-day window, metrics.previousRank and rankDelta count from its oldest reading there: metrics.since is that day and meta.windowNote says so, and a figure that cannot be given is null with nullReasons.
  • In /partners, isOwnPage is true for the shop's main page, its official pages named like the brand and a page named as the brand (creators can be ranked official too), and a null reach or spend has nullReasons.
  • The first page of /ads with adCopyHashes has meta.latestAdDate and dataFreshnessLagDays, and with status=active meta.stoppedCount.
  • /demography is the audience in the EU and the UK, and a country under a ten-thousandth of the top one moves from countryDistribution to otherCountries.
  • /ad-copy-evolution and /headline-evolution have a point for every recorded day (0 when the text was not used, null on a day cut at the texts it keeps), rank texts by the newest day and leave out the days the data source read wrong (live ads under a tenth of the days around them, one day or 2 or 3 in a row, or far fewer texts than the days on both sides), as meta.periodNote says; meta.recordedDays counts the days. Weekly and monthly /time-series live ads leave out 2 or 3 such readings in a row too.

Also changed on October 20, 2026 (brand tracker reports, lookup and Google reach):

  • In /ad-rank, /scaling-ads and /v1/workspace/scaling-ads every rank of a row comes from the ad's rank history: metrics.currentRank is its reading of the day the ad library's rank was read (the rank /top-ads shows; the library can be a day behind the history), else its newest reading, the trajectory ends on that day, and with no reading on the day the window starts the oldest reading inside it counts (the data source's own change over the window is no longer used).
  • The ad library's first 50 ads (10 per brand across brands) are ranked again by these figures: an ad that gained less than minRankDelta, or ranks below maxCurrentRank, by them is left out (an ad whose rank history gives no gain, by the ad library's own count), pagination covers the ads kept and meta.rankNote says what was read and left out, across brands too.
  • A daily /time-series (and the overview's graph) is null on a day whose live ads the data source read wrong (under a tenth of the days on both sides of it; the newest day stays as read, in the text evolutions too), its launches too, and so are the launches of the day after it when they are nearly all its live ads; weeks and months leave those launches out, and leftOut lists the days. /landing-page-evolution leaves those days out of every page, and a page's own reading under a tenth of the readings on both sides, as its meta.periodNote says, with the day the history reaches when it is behind.
  • A /testing batch with no reach counted has nullReasons stats.reach no_eu_reach unless one of its ads is not counted yet (not_measured) or all were shown outside the EU and the UK (eu_uk_only); a /partners row's missing reach and spend are not_measured only in the 7 days after its launchDate, no_eu_reach after.
  • /creatives names an ad of several images or videos carousel (it was unknown).
  • In GET /v1/lookup, a shop's signals.monthlyVisits is null for a site not measured yet (nullReasons not_measured; it was 0), the exact shop row's live ads (with every type, shop too) are its main page's as its ad overview reads them, its mainPageActiveAds, and the rows of the shop's own pages read theirs the same way, a tracked brand's signals.monthlyVisits (and its totalTraffic in GET /v1/brandtrackers) is null for a site not measured yet and says why it is missing (not_measured, or no_shop for a page with no shop), and on Free a page's reach that no plan has keeps its reason (eu_uk_only, not_measured), in advertiser lists too.
  • A Google ad's null reach.value has nullReasons (not_reported, eu_only), except for a reach the plan leaves out.
  • In GET /v1/shops/{shopId}, advertising.mainPageActiveAds is the main page's live ads as its ad overview reads them, the count its Main page in linkedAdvertisers shows (it was the shop index's count, which can be a day older).

Also changed on October 20, 2026 (TikTok and emails):

  • A TikTok row's metrics.engagementRate is (likes + comments + shares + saves) / views as a fraction (0.0513 is 5.13%; searches sent a percent and GET /v1/tiktok/library/{itemId} another metric), and daysRunning is the days since the post was published, in both.
  • metrics.rank is the post's rank among its creator's posts (1 is the best).
  • profile.followers is null when the data source has not counted them (it sent 0), content.category is null for its catch-all All, and content.hashtags are the post's tags, once each, spelled as in its description and without the punctuation after them (a record's are the data source's list of them, a search row's those of the description).
  • A TikTok record adds profile.adsCount, organicCount and avgPostsPerWeek90d, fills profile.pageCreation, and has null links for a row of the data source with no TikTok behind it (an id of fewer than 15 digits, or published before August 31, 2016, 22:00 UTC).
  • sortBy=longestRunning starts at the first TikToks (August 31, 2016, 22:00 UTC).
  • An email record names its promotion type, category and event, and its shop's monthly visits, live ads, products and 90-day figures are those the email lists show, as are the email stats' last90Days figures.
  • An email row leaves out extra.shopActiveAds for a 0 with no ad total (its nullReasons say not_measured), and an email record's shop.marketing.activeAds is then null; when the shop's figures could not be read, the record has meta.partial, a warning and nullReasons failed for them.
  • In the MCP tool analyze_shop_emails, dominant ranks campaign types, categories, promotion types and events each on its own and leaves out No Promotion and No Event.

Changed on October 21, 2026:

  • A TikTok item's metrics.views, and its likes and saves that read 0 beside them, are null with nullReasons not_measured (and so is engagementRate) when the data source sent 0 views next to likes, comments, shares or saves above 0, in searches and in GET /v1/tiktok/library/{itemId}; sortBy=views or likes with order=asc lists the posts with their views counted (minViews 1).
  • A Meta ad search with websiteIds lists the shops' own ads: every ad of a shop's main page and of its official pages named like it, and the ads of its other pages (creators, publishers and partners who ran its ads) that link to the shop or to a site on its domain; until the list is read to its end, the search's pagination.total is then the ads of the shop's own pages searched, an estimate (pagination.totalEstimated true), or null when the search names none of its own pages.
  • With sortBy=longestRunning, each batch of ads read from the data source is put in order of daysRunning.
  • In GET /v1/shops/{shopId}, advertising.activeAds counts the live ads of the shop's own pages (linkedAdvertisers[].isOwnPage), and in its /products a ranked best seller has the title, price and image of catalog.bestSellers (a best seller's price can be the lowest of its variants').
  • A shop's traffic.monthlyVisits (and growth30d) is null with not_measured when it reads 0 since its history went to 0 next to a sales estimate above 0 and units sold, in records, listed and similar shops and the lookup; such a domain is still extra.storeWide.
  • In GET /v1/ads/{adId}, advertiser.totalReach is the last reading of pageAnalytics.reachHistory while that reading is at most 2 days old (extra.pageRecordReach then holds the record's total), extra.advertiserTotalAds is filled from the page's listed figures (not_measured without one), the 7-day and 30-day reach gains of an ad started inside the window are all its reach, and a gain below that of fewer days is null (not_measured).
  • A brand tracker's statistics.ctaCount names each call to action as content.callToAction does ("Shop now").

Also changed on October 21, 2026 (shops):

  • In GET /v1/shops/{shopId}, advertising.history is the main page's live ads by day on every plan (on Free it counted every page's), and the docs say that advertising.summary reach and spend, extra.adsLaunched30d, extra.totalAds and extra.estimatedSpendUsd cover every page of the shop, where advertising.activeAds counts its own pages.
  • A shop's catalog.productsCount of 0 with no product listed, next to visits, a sales estimate or units sold, is null with not_measured, in records, listed shops and the meta.productsCount of GET /v1/shops/{shopId}/products; sortBy=productsCount leaves those shops out, and with order=asc sends minProductsCount 1 unless a products minimum is given.
  • A Meta ad search of a shop narrowed to pages that are not its own (trackedPages) that ends early says why in meta.warnings, without asking to narrow it.
  • GET /v1/filters/shops says in meta.warnings when the data source lists no values, and names the lists that give them.

Also changed on October 21, 2026 (paging, emails and ad lists):

  • Paging an advertiser search no longer fails when the data source will not continue it (it answered 503, and a retry did not help): its first 100 results are read in one call, and the page that reaches the end of what can be read answers hasMore false, with meta.partial true and a warning that says how far the search reads.
  • A page that starts past a search's exact total is empty, with hasMore false.
  • A TikTok search sorted by views or likes with order=asc starts at the first TikToks (August 31, 2016, 22:00 UTC), as longestRunning does, and a TikTok item's metrics.views (and engagementRate) is null with not_measured when it reads fewer views than likes.
  • An email's content.bodyPreview and bodyLength, and a record's content.body, are null with not_measured where the data source sent its placeholder for a body it has not read.
  • Date-times the data source gives in UTC are written one way in lists and records alike, with +00:00 and no trailing zeros in the fraction of a second (2026-09-30T00:20:11.507+00:00; the times your own boards, favorites, brand trackers and share links were created or changed end in Z, as before), and email rows carry the ids of their category, promotion type and event, as the email's record does.
  • Every paged list answers pagination.hasMore, and GET /v1/google-ads/facets/countries answers a pagination object.
  • A request body that is not valid JSON answers 400 validation_failed with the message "The request body is not valid JSON." and details.position, the character where it breaks off.
  • In Meta ad lists a row's reach is the ad index's reading, which can be a day behind the ad's record, and its reach gains are null beside a known reach when the data source lists none (not_measured), except over a window the ad started in, where it gained all the reach its row reads; in GET /v1/ads/{adId} a gain that is null beside a known reach has not_measured too.

Changed on October 22, 2026 (the Free plan):

  • The API and the MCP server moved to paid plans: a key of an account on the Free plan answered 403 plan_not_eligible on every endpoint except GET /v1/account, with details.upgradeUrl, and nothing was counted. No key could be made on Free.
  • The Free plan has changed since: The Free plan says what it includes now.
  • A key made on a paid plan is kept, and it works again as soon as the account is back on a paid plan. Share links made by an account on Free are paused the same way.

Also changed on October 22, 2026 (shop reports and records):

  • In GET /v1/shops/{shopId}/ad-ranking/series, rankDelta is the end rank minus the start rank (negative when the ad moved up, as in every ad; it was the places gained) and improvementPercent is now improvementPct, a fraction; each row of /ad-ranking carries the same two figures over the ranking's window in rank.
  • In a tracked brand's /activity/calendar, a calendar day and /activity/calendar/days, meta.partial is true or false, meta.partialSources names the sources read in part (on /calendar and a day), and preview times are UTC, a TikTok post's too.
  • In GET /v1/shops/{shopId}/landing-pages/detail, activeAds falls back on the page's ads, shareOfAds is linkedAdsTotal out of shopActiveAds, snapshots counts the days the page was captured, lifetimeAds and impressions are gone (the impressions were the reach again), a reach of 0 is null with nullReasons.reach no_eu_reach, and linkedAds have the fields of an ad search's rows.
  • A shop's /feed lists its own Meta ads, as its ad searches do.
  • GET /v1/market/q4-overview takes any from and to inside the season.
  • In /q4-season, winners lists each sale's key with its creatives, and landing page urls carry their scheme.
  • The Shopify detectors read a store at its domain without www..
  • GET /v1/advertisers/{advertiserId} and a tracked brand's landing pages, audience and media mix echo a past day in meta.snapshotDate.
  • When a shop's Meta ad statistics cannot be read at that moment, GET /v1/shops/{shopId} answers meta.partial true with a warning: its reach, the spend estimates made from it and its media and format mix are null with nullReasons failed, its ads by country are counted as its search row gives them, and the answer is not kept, so the next call reads them again (the competitor brief carries the same meta.partial and warnings).
  • A landing page on the shop's own domain, or a subdomain of it, is toShop true in /v1/shops/{shopId}/advertisers and /advertisers/{advertiserId}/landing-pages; when the shop's domains leave that domain out, meta.domains lists it first from its pages' landing pages (fromLandingPages true, a lower bound), and a page's shopAds is never fewer than the live ads of its landing pages on the shop (shopAdsAtLeast true when raised).
  • In GET /v1/tiktok/library/{itemId}, profile.latestPosts[].mediaUrl is the post's video, or null with nullReasons not_reported (it was the cover image).
  • An advertiser search reads its first 100 results and says it ends on the page that reaches the 100th (hasMore false and the warning), not on the empty page after it.
  • A TikTok search sorted by views or likes with order=asc now leaves out the posts whose views are not counted (fewer views than likes), and its pagination.total is an estimate (totalEstimated) until the list is read to its end; every other order lists them, their views null.

Also changed on October 22, 2026 (saved items and ad hooks):

  • New: GET /v1/boards/search finds what you saved, across every board and your favorites, by the words of what each saved copy shows (every word must appear, in any order; case and accents are ignored), its id or its board's name, and takes sourceType, boardId, savedFrom and savedTo; it reads your saved items only, never the data source (MCP find_saved_items).
  • New: POST /v1/tools/ad-hooks writes three short opening lines for an ad of your product, and GET /v1/tools/ad-hooks gives your allowance: no monthly limit on paid plans, and a limit a minute (429 with Retry-After); reading the allowance is not counted (MCP write_ad_hooks).
  • The MCP server has 64 tools.

Also changed on October 23, 2026 (saved views and shop filters):

  • New: GET /v1/views lists the searches you saved on the website's list pages, each with the search it makes (request: the search, searchType, sortBy, order and named filters, as the search endpoints take them); POST /v1/views saves one, PATCH /v1/views/{viewId} renames, moves or changes it and DELETE /v1/views/{viewId} removes it. They read and write your own views only, never the data source (MCP list_saved_views).
  • Shop searches take excludeCurrencies (currency codes such as EUR), socialNetworks (instagram or tiktok: a shop with any of them) and shopifyPlan (headless). trafficGrowth also reads 90 days (min90, max90) and adsGrowth 7 days (min7, max7), or a rule's period (last90d, last7d); min and max stay the last 30 days.
  • The MCP server has 65 tools.

Also changed on October 23, 2026 (product links):

  • In GET /v1/shops/{shopId}, each of catalog.bestSellers carries handle and productUrl, the product's page on the shop's own site: the address the data source gives when it is on the shop's domain (or a subdomain of it) or its myshopify domain, else https://<domain>/products/<handle> when its handle is known, else null.
  • In GET /v1/shops/{shopId}/products, productUrl follows the same rule, so an address on another site is no longer given, and handle is null when it is no single part of an address.

Also changed on October 23, 2026 (shop rows, similar shops and products):

  • A shop's createdAt (the shop record, shop rows and similar shops) is a Shopify store's creation date only. For a site off Shopify the data source gives the day it began tracking the site, not its creation: createdAt is now null (nullReasons tracking_date) and that day is the new trackedSince. A date on or before January 1, 2000 is the data source's placeholder and is null (not_reported).
  • Shop rows' catalog.bestSellers carry handle, productUrl (the rule of the shop record's) and rank (1 is the best seller), and rows carry profile.isHeadless and catalog.myShopifyDomain, as the shop record does.
  • A shop row's googleAds.reach.value is null: shop rows carry no Google reach, which is on the shop record (extra.googleAds.reach).
  • Similar shops (GET /v1/shops/{shopId}/similar, the record's similarShops) keep their extra (logo, Trustpilot, sales history). A similar list the data source stops before its end answers meta.partial and a warning on the page that reaches that point.
  • In GET /v1/shops/{shopId}/products, createdAt and publishedAt were the shop's own clock sent as UTC (8 hours early for a shop on US Pacific time). They are now UTC, with the new updatedAt, from the shop's offset from UTC (meta.shopUtcOffset, such as -08:00). When no offset can be read, the three are null (local_time) and createdAtLocal, publishedAtLocal and updatedAtLocal give the shop's clock, without a zone.
  • A product listed only among the shop details' best sellers has a null publishedAt and updatedAt (not_reported): the data source's were copies of its creation time.
  • Each product says which lists it is in (lists: bestSellers, newest) and its place among the best-selling ones (listPosition, 1 to 100).

Also changed on October 23, 2026 (shop records):

  • In GET /v1/shops/{shopId}, extra.googleAds.reach.value was always null: it is now the shop's Google EU reach, with lowerBound and upperBound, and extra.googleAds adds reachHistory, history (its Google ads marked active by week), updatedAt and latestAds.
  • A social network's growth30d is now the 30-day change of the followers overview (it was another window for some Facebook pages: 0.3636 where the change was 0.2898). GET /v1/shops/{shopId}/socials gives it as growth30d too.
  • The shop's X profile is socials.x. socials.twitter is renamed socials.x and stays, the same object, for one release. Each network has url, and socials.others lists the shop's other links.
  • tiktok.profileMetrics.percentAds is a percent (0 to 100); the new adsShare is the same as a fraction. tiktok adds avatarUrl, history, postsChange30d, postsChange30dPct and latestAds, and tiktok.activity.avgActiveAds7d and avgActiveAds30d, null before, average its TikTok ads by day.
  • New on paid plans: advertising.summary.firstAdSeenAt, longestRunningDays, medianRunningDays, landingPagesCount and the 30-day changes of the live ads, launched ads and EU reach (activeAdsChange30d, launchedChange30d, reachChange30d, each also as a fraction, ...Pct), and advertising.runningDaysMix, reachCountries, reachHistory, topLandingPages, adsByAgeRange and adsByGender. On every plan: advertising.allPagesHistory and advertising.topCountries[].ads.
  • New: catalog.bestSellers[].rank, sales.hasSubscription, technology.apps[].appStoreUrl and categories, profile.isHeadless, extra.updatedAt, and the createdAt and trackedSince of the shop dates above.
  • GET /v1/shops/{shopId}/advertisers adds each page's logoUrl and moreLandingPages, a profileUrl where the ad overview has none, and each domain's landingPagesCount and moreLandingPages.

Also changed on October 23, 2026 (products):

  • New: GET /v1/products and POST /v1/products/query search and browse store products, each with its price, sales estimates, units sold, reviews, best seller rank, Meta ads, EU reach and spend, selling countries, launch date and shop, sorted by relevance, newest (the launch date), activeAds or spend (EU ad spend over the last 30 days) (MCP search_products). searchType matches the text against the product's name or its shop's domain, and the named filters bound the price in USD, the active ads, the ad share, the number of reviews and the launch day, and take currencies and subscription; GET /v1/filters/products lists the currencies they take.
  • shop (one shop's domain or id) lists that shop's products only, with no search text beside it, on the product search and in search_products. Boards save products (sourceType product) as a search last showed them, and the search of everything saved finds them by their title and shop.
  • The MCP server has 73 tools.

Also changed on October 23, 2026 (product filters):

  • The product search takes more named filters: the sales estimate of a month or a day (minEstMonthlySales, minEstDailySales and their maximums; a day's bound is 30 days of it), units sold a month or a day (minUnitsSoldMonthly, minUnitsSoldDaily), sellingCountries (a product that sells to any of them), shopCountries, the review score (minRating, maxRating), minAdsLaunched (Meta ads launched in the last 30 days), minSpendShare, minEuReach (the EU reach over 30 days), hasPartnershipAds, promoTypes (percent-off) and minShopProductsCount, each with its maximum where it has one; GET /v1/filters/products lists the shops' countries too.
  • sortBy takes estSales (the sales estimate), adPressure (the ad share) and bestSelling (the best seller rank in its shop, rank 1 first), and searchType takes productDescription and url.
  • Each product has its latest ads (advertising.latestAds, with their pictures in advertising.previewUrls) and its weeks (weeks: live ads, ad share, EU spend and reach a day), and bestSeller.rankPercent is its rank as a percent of the shop's products (low is better).

Changed on October 24, 2026 (parameters, failed reads and deep pages):

  • A query parameter a route does not read is refused with 400 validation_failed, whose message names it and lists the parameters the route takes, where it used to be dropped without a word (a misspelt name, or a filter sent to a route that has none, answered as if it was never sent). Searches refuse an unknown named filter as before. A plain parameter (country, mediaType, active, type) that sets a filter a named filter also sets, to another value, is refused too.
  • Brand trackers: /ads and /timeline/metadata refuse a past snapshotDate (they read the ad library as it is now), /partnership-ads an unknown sortBy, /v1/workspace/scaling-ads an unknown period, and the tracker lists a hasNewAdsSince more than 30 days back (the new-ad counters cover 30 days). /v1/workspace/hooks, /ad-copies and /landing-pages read each brand's rows in the sortBy and order asked before merging them. The website's across-brands reports send euOnly only to the reports that read it.
  • Similar shops refuse displayInTrending in filters (the list has no shop-index flag) and read its growth bounds as percentages, as a shop search does; an offset past what one request can read (600 shops on from those already read) is refused with a 400 that says how deep it can go, and a page the read stopped in has meta.partial with a warning. A shop's TikTok library refuses profile and site filters (the shop's own scope takes their place).
  • A part of an answer the data source could not read this time sets meta.partial with a warning (and the answer is not cached), never a silent gap or an empty list; an answer of the data source that is not JSON is a 503 upstream_error, and a saved shop, a new tracker or an email option list whose read fails answers the error, never not_found. A page deeper than one read of a list that leaves rows out reaches has meta.partial and hasMore true, and a brand's ad copies, partners and creative tests say with meta.partial when one read does not cover the brand.
  • GET /v1/google-ads/facets/networks takes search, limit and offset, as the other option lists. metric of /v1/shops/compare is required (the reference said optional).
  • MCP: a tool refuses an argument its chosen kind does not read (shop_report, lookup_filter_ids, market_overview, scan_advertiser) and arguments that disagree (trend_signal with sort_by, active_only with status, a named argument with filters); creative_inspiration_pack ranks every keyword's ads together.

Also changed on October 24, 2026 (search by image):

  • New: POST /v1/products/image-search finds the store products that look like a picture, each with its shop, the closest first. Send the picture as multipart/form-data: a PNG, JPG or WEBP file of 10 MB at most (image), or a direct image URL (imageUrl), which we download ourselves. Each row is a product row as the product search answers it, with similarity (0.7 to 1) and matchOnly (a match the product index has no record of: its title, picture, price, launch date and shop only).
  • The search takes the product search's named filters, sortBy (relevance, estSales, activeAds, adPressure, newest, spend, spend14d) and maxPerShop (the closest 1, 3, 5, 10 or 20 matches of each shop), in pages of up to 32. GET /v1/products/image-search/{searchId} reads its other pages, sorts, filters and results per shop without sending the picture again, and GET /v1/products/image-search/history lists your own recent image searches.
  • The picture is written again before it is searched, as a JPEG without its metadata (EXIF, location, comments), and an image URL never leaves our servers. New errors: 400 invalid_image, 400 unsupported_url and 422 unreadable_image.
  • On the Free plan, image search is ranked by relevance, with no filters. The MCP server has 67 tools: search_products_by_image is new.

Changed on October 25, 2026 (credits):

  • The API and the MCP server are metered in credits instead of requests: 1 credit = 1 result returned: one brand's details, one ad, or one row of a list. An empty result is free. A call costs the results it returns, and the plans' monthly allowance is in credits.
  • Metered answers send X-Usage-Cost, X-Credits-Used, X-Credits-Remaining and X-Credits-Source; GET /v1/usage reports the top-up credits under credits.topup.balance.
  • 402 insufficient_credits comes once the month's credits and the top-up credits are both used up, with details.upgradeUrl and details.topUpUrl.
  • The rate limit is shared by the whole workspace.

Share links (shareUrl) open a web page on https://sellwinners.com that anyone can view. The same record is available as JSON from /v1/shared/ads/{token} and /v1/shared/boards/{token}. A link whose owner is on the Free plan answers 403 forbidden until the owner is back on a paid plan.

The identity endpoints /v1/me, /v1/usage and /v1/workspace return their objects at the top level, next to requestId. The system endpoints /v1, /v1/health and /v1/system/freshness carry no requestId, and /v1 and /v1/health answer a plain object without data. The request id is also sent in the X-Request-Id header. Quote it when you contact support.

Boards, favorites and brand trackers also have POST, PATCH and DELETE endpoints. They take a JSON body, sent with Content-Type: application/json.

Pagination

List endpoints take limit (up to 100 on searches; facet listings take up to 500 and a brand's /snapshots up to 365) and either page (1, 2, 3...) or offset. When both are sent, offset is used. The default page size is listed with each endpoint. Ad, Google ad, TikTok, email and media listings answer with:

"pagination": { "page": 2, "limit": 25, "total": 1840, "totalPages": 74, "hasMore": true }

Shop, product and advertiser listings, and the ads of one advertiser, answer with:

"pagination": { "limit": 32, "offset": 32, "total": 5120, "hasMore": true }

To get the next page, repeat the same request with page plus one, or with offset plus limit. In a POST …/query body, send "page" or "offset" as fields. hasMore is false on the last page. When the data source will not continue a search past some point, the page that reaches it answers hasMore false with meta.partial true and a warning that says how many results can be read. Paging reaches the first 5,000 results of a search (an advertiser search, its first 100). Narrow the search with filters or change the sort to see other results.

Google ad listings return an exact total, except a list the status or days-running rule narrows (see the Google ads search). A "totalEstimated": true marks a total (and its totalPages) that is an estimate until the list is read to its end, as on a shop's similar shops and a Meta ad search of a shop (websiteIds).

Boards, favorites and brand tracker reports take page and limit and answer with page, limit, total, totalPages and hasMore. Facet lists, a shop's /products and its /similar shops take limit and offset and answer with limit, offset, total and hasMore.

Sorting & filters

Search endpoints accept sortBy and order (desc by default). When you pass a search term, results are sorted by relevance unless you choose another sort; without a search term the default is newest (shops and products: relevance, media: reach). Google and TikTok ad searches are always ranked by relevance; there, sortBy applies when you browse without a search term.

Each data source has a POST …/query endpoint that takes a JSON body with query, filters, sortBy, order, limit and page (or offset) for advanced filtering. Use the facet endpoints to see the values and ids the filters take.

Filters can be sent by name: as extra query parameters on a GET search (?status=active&minDaysRunning=30&mainCountries=US,GB) or as top-level fields of a POST …/query body ({"status": "active", "minDaysRunning": 30}). Each endpoint below lists the names it takes. On the search endpoints a filter name the endpoint doesn't support returns a 400 validation_failed that lists the supported ones, so a typo never silently returns unfiltered results; the brand tracker reports ignore names they don't know. Lists take comma-separated values or a JSON array, dates use 2026-01-31, and the raw filters object still works alongside named filters.

Growth filters (trafficGrowth, adsGrowth, pageReachGrowth, adReachGrowth) take rules written as {"comparison": "greater" | "lower", "value": 50} or {"operator": "gte" | "lte", "value": 50}. Values are percentages over the last 30 days; other periods are not available. minRankDelta is the minimum number of positions an ad gained over rankDeltaWindow (7d unless you send 14d or 30d). hideSavedAds leaves out the ads you already saved. Category ids for every categoryIds filter come from /v1/facets/categories.

Rate limits & credits

PlanCredits / monthRate limit
Starter5,00060 / minute
Pro15,000120 / minute
Business20,000300 / minute

1 credit = 1 result returned: one brand's details, one ad, or one row of a list. An empty result is free. Each plan includes credits for the month, renewed at 00:00 UTC on the 1st. A call costs the results it returns, so a smaller limit costs less, and an MCP tool call costs the results it returns, like the API. Credits and the rate limit are per workspace: everyone in it, all its keys, the API and the MCP server share one pool of credits and one rate limit. On a paid plan, the workspace's owner can buy top-up credits on the billing page (€1 buys 120, from €10): they are used after the month's credits, carry over and never expire.

CallCredits
A search or a list1 per result returned
One record (a shop, an ad, an email)1
An empty result0
A change (save, move, share, delete)1 (an item already on the board: 0)
A search by image4 per result returned
A shop's sales history4
Lookups, filter values (facets), GET /v1/account and GET /v1/usage0
An error or a refusal0

Every metered response includes:

X-RateLimit-Limit       requests allowed per minute
X-RateLimit-Remaining   requests left this minute
X-Usage-Cost            credits this request cost
X-Credits-Used          credits this request cost (the same number)
X-Credits-Remaining     credits left after this request (monthly and top-up)
X-Credits-Source        recurring, topup or hybrid (when it cost credits)
X-Quota-Limit           credits included this month
X-Quota-Remaining       monthly credits left
X-Quota-Reset           when the monthly credits renew (UTC)
X-Request-Id            the id of this request

Over the per-minute rate limit you get 429 rate_limited with a Retry-After header (in seconds). When the month's credits and the top-up credits are both used up you get 402 insufficient_credits, with details.upgradeUrl and details.topUpUrl, until the monthly credits renew. Check your credits any time with GET /v1/account or GET /v1/usage. These calls cost nothing, still send X-Usage-Cost: 0, X-Credits-Used: 0 and X-Credits-Remaining, and work even when the credits are used up.

These limits apply to the API and the MCP server, on paid plans and on Free. The web app on the website is not metered: on paid plans it is unlimited within fair use.

The Free plan

The Free plan includes the web app and the MCP server (150 credits a month), without the API. A Free account makes a key for the MCP server (AI agents) in its dashboard, within 150 credits a month and 10 requests a minute; the REST API is on paid plans: with a Free key it answers 403 plan_not_eligible, with details.feature, details.requiredPlan and details.upgradeUrl, on every endpoint except GET /v1/account, and nothing is counted. A key made on a paid plan is paused on Free, and it works again as soon as the account is back on a paid plan. On Free, a search answers its first results and a tool or endpoint whose data Free does not include answers with the paid plans' message. The plan comparison shows what Free includes. The demo brands are open in full on the website.

Errors

Errors use standard HTTP status codes and a JSON body:

{
  "error": {
    "code": "invalid_api_key",
    "message": "This API key is invalid or has been revoked.",
    "requestId": "req_8f2c1a9b4d7e6f3a2b1c0d9e",
    "details": null
  }
}

code is stable and safe to branch on, message is written for people, and details carries extra data when there is some (the rejected fields of a 400; the monthly credits, their renewal date, upgradeUrl and topUpUrl of a 402).

StatuscodeMeaning
400validation_failedA parameter, filter or body field isn't valid. message explains which.
400invalid_image / unsupported_urlAn image search's picture isn't a PNG, JPG or WEBP file of 10 MB at most, or its URL isn't a public http or https address.
401missing_api_key / invalid_api_keyNo key was sent, or the key is wrong or revoked.
402insufficient_creditsThe month's credits and the top-up credits are used up. The monthly credits renew on the 1st of the month; you can buy top-up credits or upgrade your plan (details.topUpUrl, details.upgradeUrl).
403plan_not_eligibleYour plan doesn't include this. On the Free plan, that is every request except GET /v1/account. details names the feature, the requiredPlan and an upgradeUrl.
403workspace_public_api_suspendedThe account was disabled. Contact support.
403forbiddenThis key cannot do this.
404not_foundThe resource or id doesn't exist.
409conflictThe change clashes with what is already saved, such as an item that is already on the target board.
422unreadable_imageAn image search's picture could not be read, or its URL could not be downloaded. Try another file or URL.
429rate_limitedToo many requests this minute. Wait for Retry-After seconds.
500internal_errorSomething went wrong on our side. Safe to retry.
503upstream_error / service_unavailable / service_busyA temporary problem on our side. Safe to retry with backoff (Retry-After).
503upstream_timeoutThe search took too long. Narrow it with fewer or tighter filters, or retry. (502 and 504 before October 27, 2026.)

Media URLs

Images and videos in responses are served from our CDN at https://api.sellwinners.com/v1/media/file/…. These URLs don't need an API key and don't use credits, so you can embed them directly in <img> and <video> tags. A file the data source no longer has is sent as null for a day, and a missing file answers an empty 404 of its media type. Product images and app icons hosted on Shopify's CDN are served from our CDN too. To show an image small, add ?w=96 (thumbnails) or ?w=480 (cards): a JPEG, PNG, WebP or GIF image is then sent as WebP at that width at most, never made larger; an animation, a smaller image or a video comes as it is. For a flat, display-ready list of creatives, use /v1/media.

To show an image at its own size but lighter, add ?w=full: a JPEG, PNG, WebP or GIF image is then sent as WebP at its own width and height, at a quality that looks the same, when that saves at least a tenth of the file; otherwise, and for an animation or a video, the original comes as it is. Without w, the original file is sent.

Discovery

Turn a name, a domain or a page id into the ids the other endpoints take.

GET/v1/lookup

Find a brand, advertiser or shop. Results are ranked best first (score). A domain: the site with exactly that domain (exact, also outside the shop index), its subdomains, the same name under another suffix, then the sites whose domain only contains it (fuzzy); the shop's own Facebook pages (its main page exact, then its official pages, those named like the shop first), then the pages named like it, exact when they link to the domain. A name: the brand's own site (the website of its page of that name) first, then its own pages as a domain lists them, then the shops and pages found by the name; with the brand's site found, a shop or page that only contains the name is left out, and a site of that name is exact only when it runs ads (else with traffic or ads). Official pages of another name with no live ad come after the pages found by name, and pages that never advertised last. A shop's signals.activeAds are its main page's live ads: read now on the shop's own row when its pages were read (signals.activeAdsSource page: its ad overview's reading, the shop record's mainPageActiveAds; the shop's own pages read theirs the same way), else the shop index's count, which can be older (index); a tracked brand has its page's live ads and its shop's monthlyVisits (null with nullReasons not_measured, also for a site not measured yet, which reads 0, or no_shop for a tracked page with no shop). A shop's signals.monthlyVisits is null for a site the data source has not measured yet (nullReasons not_measured: it reads 0), or one at 0 since its history went to 0 next to a sales estimate and units sold. signals.reach30d and signals.totalReach are EU reach: when one is null, nullReasons says why (eu_uk_only for a page with no EU ads and no reach, not_measured for a window the data source has not counted). To tell rows of one name apart, each carries its picture (logoUrl: a shop's, a page's, on every plan, and a tracked brand's page's), a shop its countryCode and mainMarket and signals.growth30d (its 30-day traffic growth, a fraction; null with nullReasons not_measured when the month before had no visits), a page the shop it links to (advertiser.domain), its mainCountry and signals.facebookLikes, and a tracked brand its shop's id (brandtracker.shopId).
ParameterDescription
qrequired Brand name, domain (allbirds.com) or Facebook page id.
type What to look for (default auto: all of them). One of: auto, brandtracker, advertiser, shop.
limit Results, 1-10 (default 10).
curl "https://api.sellwinners.com/v1/lookup?q=allbirds.com&limit=5" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/lookup/facebook-shop

Facebook pages of a shop, or the shop of a page. Send exactly one of shopId or facebookPageId. primaryShop.monthlyVisits is the shop's monthly visits, null for a site the data source has not measured yet (nullReasons primaryShop.monthlyVisits not_measured); trafficNumber, its old name, keeps the same value for one release. primaryShop.logoUrl is the shop's picture (profilePhotoUrl, its old name, kept one release). With a facebookPageId, primaryShop.adCounts gives the shop's live and total ads on meta, google and tiktok. Each Facebook page has runningAds, totalAds, likes, createdAt and profileUrl.
ParameterDescription
shopId Shop id or domain.
facebookPageId Facebook page id.
limit Results, 1-50 (default 50).
curl "https://api.sellwinners.com/v1/lookup/facebook-shop?shopId=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

Shops

Find Shopify stores and get products, traffic, sales, socials and ads.

GET/v1/shops

Search or browse shops (trending when empty). Searches keep to the shop index, not every website the data source tracks. A domain search (searchType=domain) lists the site with exactly that domain first, with extra.exactDomainMatch true, also when the shop index leaves it out (extra.inShopIndex is false then); not with other filters or another sort. languages takes two-letter codes (fr; names such as french are converted); themeIds, pixelIds and shopifyAppIds take ids from /v1/facets/themes, /pixels and /shopify-apps, not names. Growth ranges are percentages over 30 days (trafficGrowth also takes min90 and max90, over 90 days, and adsGrowth min7 and max7, over 7 days; a rule's period may be last90d or last7d the same way); excludeCurrencies takes currency codes such as EUR, socialNetworks instagram or tiktok (a shop with any of them) and shopifyPlan headless. A listed shop's advertising.activeAds are its main page's live ads as the shop index counts them, which can be a day or more behind its shop record (GET /v1/shops/{shopId} reads them now). A shop row's createdAt is a Shopify store's creation date: a site off Shopify has the day the data source began tracking it in trackedSince instead (createdAt null, nullReasons tracking_date), and a date on or before 2000-01-01, the data source's placeholder, is null (not_reported). Its catalog.bestSellers carry handle, productUrl (its page on the shop's own site, as on the shop record) and rank (1 is the best seller); profile.isHeadless and catalog.myShopifyDomain are as on the shop record. A row's googleAds.reach.value is null: the Google EU reach is on the shop record only (extra.googleAds.reach). A sales sort (estMonthlySales, unitsSold) lists one row per Shopify store: the domains of one myshopify domain read together share the store's sales, so they are one row, the most visited, naming the others in extra.sharedSalesWith (a store's domains further down the list are left out too), and its pagination.total is null until the list is read to its end; sortBy=estMonthlySales with order=asc leaves out the shops with no sales estimate or one under 100 USD (minMonthlySales 100) unless a sales bound is given, and those whose estimate is null; sortBy=growth30d leaves out the shops with no traffic growth or no visits in the latest month (with order=asc, minMonthlyVisits 1 unless a visits minimum is given); sortBy=productsCount leaves out the shops whose count is raised to the best sellers they list (catalog.productsCountAtLeast: the data source ranks by its own count) and those whose count is null (with order=asc, minProductsCount 1 unless a products minimum is given); these have a null pagination.total until the list is read to its end. A sales estimate of 0 next to units sold is null (no_estimate), and so is one too low for its units sold at the shop's own prices: under a hundredth of the median price of its listed best sellers a unit sold (0.50 USD for a shop that lists none), or under a tenth of that price a unit sold while worth under five of its median-priced products: too_low, the data source's floor, not a figure; extra.storeWide marks a domain with 0 visits that carries its Shopify store's sales (a measured 0 or one since its history went to 0, its visits null then, or its store's other domains are named); nullReasons says why an estimate is null (no_estimate, too_low, or not_shopify: sales are estimated for Shopify stores only), and why monthlyVisits (not_measured: a site the data source has not measured yet, or one at 0 since its history went to 0 next to a sales estimate and units sold, its growth30d null too), growth30d (not_measured: no visits the month before; -1, every visit lost, when the latest month has none after a month with visits), unitsSold or productsCount is null (productsCount not_measured also for a count of 0 with no product listed next to visits, a sales estimate or units sold: a count the data source has not made). catalog.productsCountCapped marks the data source's products ceiling (25,001: 25,000 or more), and catalog.productsCountAtLeast a count raised to the best sellers the row lists (the data source's count is behind them).
Named filters 52extra query parameters
adsGrowthadsTimePeriodcategoryIdscountriescreatedAftercreatedBeforecreationCountriescurrenciesdisplayInTrendingexcludeCreationCountriesexcludeCurrenciesexcludeLanguagesexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdshasProductshasTikTokisShopifyPluslanguagesmainMarketCountriesmarketCountriesmaxActiveAdsmaxActiveAdsGrowthmaxAdvertisersCountmaxBestSellerPricemaxEstimatedRevenuemaxMonthlySalesmaxMonthlyVisitsmaxProductsCountmaxTrafficGrowthmaxTrustpilotRatingmaxTrustpilotReviewCountmaxUnitsSoldminActiveAdsminActiveAdsGrowthminAdvertisersCountminBestSellerPriceminEstimatedRevenueminMonthlySalesminMonthlyVisitsminProductsCountminTrafficGrowthminTrustpilotRatingminTrustpilotReviewCountminUnitsSoldpixelIdsshopifyAppIdsshopifyPlansocialNetworksthemeIdstrafficGrowthvisitorCountries
ParameterDescription
search Shop name, domain or keyword.
searchType What the search text is matched against (default name). all is the same as name. One of: name, domain, productName, shopContains, all.
country 2-letter ISO code of the country the shop was created in.
sortBy Defaults to relevance when searching, otherwise relevance. One of: relevance, newest, monthlyVisits, activeAds, productsCount, growth30d, advertiserCount, spend, estSales, unitsSold, createdAt, estMonthlySales.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 32).
curl "https://api.sellwinners.com/v1/shops?search=shoes&country=US&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/shops/query

Search shops with advanced filters. Searches keep to the shop index, not every website the data source tracks. A domain search (searchType=domain) lists the site with exactly that domain first, with extra.exactDomainMatch true, also when the shop index leaves it out (extra.inShopIndex is false then); not with other filters or another sort. languages takes two-letter codes (fr; names such as french are converted); themeIds, pixelIds and shopifyAppIds take ids from /v1/facets/themes, /pixels and /shopify-apps, not names. Growth ranges are percentages over 30 days (trafficGrowth also takes min90 and max90, over 90 days, and adsGrowth min7 and max7, over 7 days; a rule's period may be last90d or last7d the same way); excludeCurrencies takes currency codes such as EUR, socialNetworks instagram or tiktok (a shop with any of them) and shopifyPlan headless. A listed shop's advertising.activeAds are its main page's live ads as the shop index counts them, which can be a day or more behind its shop record (GET /v1/shops/{shopId} reads them now). A shop row's createdAt is a Shopify store's creation date: a site off Shopify has the day the data source began tracking it in trackedSince instead (createdAt null, nullReasons tracking_date), and a date on or before 2000-01-01, the data source's placeholder, is null (not_reported). Its catalog.bestSellers carry handle, productUrl (its page on the shop's own site, as on the shop record) and rank (1 is the best seller); profile.isHeadless and catalog.myShopifyDomain are as on the shop record. A row's googleAds.reach.value is null: the Google EU reach is on the shop record only (extra.googleAds.reach). A sales sort (estMonthlySales, unitsSold) lists one row per Shopify store: the domains of one myshopify domain read together share the store's sales, so they are one row, the most visited, naming the others in extra.sharedSalesWith (a store's domains further down the list are left out too), and its pagination.total is null until the list is read to its end; sortBy=estMonthlySales with order=asc leaves out the shops with no sales estimate or one under 100 USD (minMonthlySales 100) unless a sales bound is given, and those whose estimate is null; sortBy=growth30d leaves out the shops with no traffic growth or no visits in the latest month (with order=asc, minMonthlyVisits 1 unless a visits minimum is given); sortBy=productsCount leaves out the shops whose count is raised to the best sellers they list (catalog.productsCountAtLeast: the data source ranks by its own count) and those whose count is null (with order=asc, minProductsCount 1 unless a products minimum is given); these have a null pagination.total until the list is read to its end. A sales estimate of 0 next to units sold is null (no_estimate), and so is one too low for its units sold at the shop's own prices: under a hundredth of the median price of its listed best sellers a unit sold (0.50 USD for a shop that lists none), or under a tenth of that price a unit sold while worth under five of its median-priced products: too_low, the data source's floor, not a figure; extra.storeWide marks a domain with 0 visits that carries its Shopify store's sales (a measured 0 or one since its history went to 0, its visits null then, or its store's other domains are named); nullReasons says why an estimate is null (no_estimate, too_low, or not_shopify: sales are estimated for Shopify stores only), and why monthlyVisits (not_measured: a site the data source has not measured yet, or one at 0 since its history went to 0 next to a sales estimate and units sold, its growth30d null too), growth30d (not_measured: no visits the month before; -1, every visit lost, when the latest month has none after a month with visits), unitsSold or productsCount is null (productsCount not_measured also for a count of 0 with no product listed next to visits, a sales estimate or units sold: a count the data source has not made). catalog.productsCountCapped marks the data source's products ceiling (25,001: 25,000 or more), and catalog.productsCountAtLeast a count raised to the best sellers the row lists (the data source's count is behind them).
Named filters 52top-level body fields
adsGrowthadsTimePeriodcategoryIdscountriescreatedAftercreatedBeforecreationCountriescurrenciesdisplayInTrendingexcludeCreationCountriesexcludeCurrenciesexcludeLanguagesexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdshasProductshasTikTokisShopifyPluslanguagesmainMarketCountriesmarketCountriesmaxActiveAdsmaxActiveAdsGrowthmaxAdvertisersCountmaxBestSellerPricemaxEstimatedRevenuemaxMonthlySalesmaxMonthlyVisitsmaxProductsCountmaxTrafficGrowthmaxTrustpilotRatingmaxTrustpilotReviewCountmaxUnitsSoldminActiveAdsminActiveAdsGrowthminAdvertisersCountminBestSellerPriceminEstimatedRevenueminMonthlySalesminMonthlyVisitsminProductsCountminTrafficGrowthminTrustpilotRatingminTrustpilotReviewCountminUnitsSoldpixelIdsshopifyAppIdsshopifyPlansocialNetworksthemeIdstrafficGrowthvisitorCountries
curl -X POST "https://api.sellwinners.com/v1/shops/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "mainMarketCountries": ["US"], "minMonthlyVisits": 50000, "page": 1, "search": "shoes", "sortBy": "monthlyVisits"}'

GET/v1/shops/{shopId}

One shop by id or domain. Profile, traffic, sales, advertising, technology, TikTok, latest ads and similar shops in one call. A domain is the site with exactly that domain (www. and a path aside), looked up among every website the data source tracks; one it does not reach answers 404 not_found. meta.partial and a warning mean the shop's listing figures (its sales estimate, ad counts and latest ads) could not be read: those stay null. extra.googleAds.liveAds counts the shop's Google ads the data source marks active (some Google no longer shows; GET /v1/google-ads with status=active lists those it shows now), from a Google ad search on the shop when the shop data has none; liveAdsExact is false for a lower bound. advertising.summary.reach30d is the EU reach of the last 30 days, summed by date; totalReach the EU reach since tracking began and extra.adsLaunched30d the ads launched in the last 30 days, summed the same way; these, extra.totalAds and the USD estimates made from the reach are the data source's ad overview's, which covers every page of the shop (linkedAdvertisers, those not its own too), where advertising.activeAds counts its own pages; the reach figures and the estimates made from them are null for a shop with no EU or UK reach (nullReasons eu_uk_only; no_ads for a shop with no Meta ad at all). The USD estimates made from the reach (9 USD per 1,000 people reached) keep two decimals under 10 USD (1.26) and are in whole dollars from 10 USD up. advertising.activeAds counts the live ads of the shop's own pages (its main page and its official pages named like it, linkedAdvertisers[].isOwnPage true: the creators, publishers and partners among its pages run other brands' ads too and are left out), mainPageActiveAds its main page's (its ad overview's reading, as its Main page in linkedAdvertisers shows it; null without one), indexActiveAds the shop index's count of its live ads, the figure shop lists show as advertising.activeAds and the activeAds sort and filter follow (null for a past day or with no search row); linkedAdvertisers[].rank is Main, Official or Whitelisting. advertising.history is the shop's live ads by day as the shop details chart them (the shop index's series, which indexActiveAds ends on; on the Free plan its main page's). nullReasons maps a null field's path to why it is null: not_shopify (sales and products are estimated for Shopify stores only), no_estimate, too_low (the data source's floor, not a figure), not_measured, eu_uk_only, no_ads (a shop with no Meta ad at all), rounded (a follower growth under the rounding of its counts), not_linked (no TikTok profile), not_on_tp (not_measured where the shop's profile carries neither a followers total nor a products count: it does not say), no_reviews, failed (not read this time: its Meta ad statistics when its ad overview could not be read, with meta.partial and a warning, its ads by country then counted as its search row gives them; such an answer is never served again from the cache). A sales estimate of 0 next to units sold is null (no_estimate), and so is one too low for its units sold at the shop's own prices (too_low): under a hundredth of the median price of its listed best sellers a unit sold (0.50 USD for a shop that lists none), or under a tenth of that price a unit sold while worth under five of its median-priced products, in the record and its sales history; extra.storeWide marks a domain with 0 visits that carries its Shopify store's sales (a measured 0 or one since its history went to 0, its visits null then, or a brand store of the same myshopify domain has the visits), extra.sharedSalesWith that brand store. traffic.growth30d is a fraction (-0.1543 is -15.4%) and traffic.history starts at the first month with visits. traffic.monthlyVisits is null for a site the data source has not measured yet (0 visits and no month with visits, not_measured) or no longer measures (0 since its history went to 0, next to a sales estimate and units sold: not_measured, its growth30d null too), traffic.growth30d when the month before had no visits (not_measured), and -1 (every visit lost) when the latest month has none after a month with visits. A social network's growth30d comes from its follower history when the data source gives 0 or none (null with less than 28 days of history, not_measured; null when two readings 30 days apart are equal and the counts are rounded coarser than 0.05%, rounded), and a network's 0 followers is null (not_measured); a network's followers and extra.followersTotal missing from the shop's profile are the followers overview's latest counts (the networks it counts, added up); extra.followersTotal is null when no network is counted (not_measured). catalog.mainCategory is the most specific category of the shop's category ids (the data source's own label only without them, and only when it is a category's name), catalog.categoryLeaves lists its categories as Parent > Leaf, and productsCountCapped marks the data source's ceiling (25,001: 25,000 or more); productsCountAtLeast marks a count raised to the best sellers it lists (the data source's count is behind them, or it has none); productsCount is null (not_measured) for a count of 0 with no product listed next to visits, a sales estimate or units sold, a count the data source has not made. A Trustpilot page with no review has a null rating. tiktok.matchedBy is null for the TikTok profile linked to the shop, socials for the followers of its own social profiles, handle for a profile found by its TikTok or Instagram handle (a match, not a link of the data source). Social networks with neither a handle nor followers are left out; socials.facebook.page is the main page when there is no handle, and a YouTube channel stored by its id has no handle: socials.youtube.channelId and url. similarShops leave out the shop itself and its own sites (the same name under another suffix or subdomain, the same myshopify domain, or one of its brand stores); extra.similarIndexed is false for a shop the similarity index does not hold yet. snapshotDate gives the profile, traffic and Meta ad figures of a past day (meta.snapshotDate); the sales estimate, products, apps and latest ads stay today's. advertising.launchedHistory is the ads launched each day on all the shop's pages, as extra.adsLaunched30d counts them. extra.googleAds carries the Google ads by country (ads and reach), network, targeting and format, with totalAds and newAds; extra.tabCounts counts its products and ads by kind and extra.trafficCountriesCount the countries its visits come from. linkedAdvertisers carry each page's totalAds, facebookLikes, profileUrl, createdAt and adLibraryUrl. catalog.bestSellers lists the shop's best sellers, each with imageUrl, title, price, currency, handle (the last part of its address on the shop, null when not known) and productUrl: its page on the shop's own site, the address the data source gives when it is on the shop's domain (or a subdomain of it) or its myshopify domain, else https://<domain>/products/<handle> when its handle is known, else null. Each best seller also has rank (1 is the best seller, as the shop details rank them). createdAt is a Shopify store's creation date: a site off Shopify has the day the data source began tracking it in trackedSince (createdAt null, nullReasons tracking_date), and a date on or before 2000-01-01, the data source's placeholder, is null (not_reported); profile.isHeadless marks a headless store and extra.updatedAt is the day the data source last read the shop. socials.x is the shop's X profile (socials.twitter is the same, its name before October 23, 2026); each network has url, its profile's address, and socials.others lists the other links (platform is the site's name, such as snapchat); a network's growth30d is the followers overview's 30-day change (a fraction). sales.hasSubscription says whether the shop sells subscriptions (null when not read). technology.apps carry appStoreUrl (the app's page on the Shopify App Store) and categories. extra.googleAds.reach is the shop's Google EU reach now, with lowerBound and upperBound (reported for ads shown in the EU only; null with not_reported when the data source reports none), reachHistory the same by week, history its Google ads marked active by week, updatedAt the day its Google figures were read and latestAds its latest Google ads. On paid plans advertising.summary has firstAdSeenAt, longestRunningDays, medianRunningDays, landingPagesCount and the changes over 30 days of its live ads, launched ads and EU reach (activeAdsChange30d, launchedChange30d, reachChange30d, and each as a fraction, ...Pct), every page's as the ad overview counts them (advertising.allPagesHistory), not its own pages' alone; advertising has runningDaysMix (its ads by days running), reachCountries (its EU reach by country, share a fraction), reachHistory (its EU reach by day), topLandingPages (with share and screenshotUrl), adsByAgeRange and adsByGender (in ads, shares as fractions); these are null on the Free plan, and failed when the ad statistics could not be read. advertising.allPagesHistory is every page's live ads by day, and advertising.topCountries[].ads its ads targeting each country. tiktok.profileMetrics.adsShare is percentAds as a fraction (percentAds is a percent, 0 to 100); tiktok.avatarUrl, history (the profile's posts, views and likes by day), postsChange30d and postsChange30dPct (a fraction) describe the linked profile; tiktok.activity.avgActiveAds7d and avgActiveAds30d average the shop's TikTok ads by day and tiktok.latestAds lists its latest TikTok ads.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
snapshotDate A past day (YYYY-MM-DD): the profile, traffic and Meta ad figures as they were then.
curl "https://api.sellwinners.com/v1/shops/allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/products

Shop products. sortBy=popularity lists the best sellers the shop's details rank first (rank 1 is the best seller), then its other listed products, unranked (meta.order bestSellers); without that ranking the products are in the data source's order, unranked (meta.order listed). When the product lists are empty, the best sellers are the list (meta.source bestSellers). Every order lists the same products (the ranked best sellers, the other best sellers, then the newest products), each with its rank, once: a ranked best seller has the title, price and image of the shop record's catalog.bestSellers, and a best seller listed among the newest products too keeps its best seller's price and image. A best seller's price is the one the shop's best sellers list, which can be the lowest of its variants' prices; the other products have the price the products list reads, at times another variant's. meta.productsCountCapped marks the data source's ceiling (25,001: 25,000 or more), and meta.productsCountAtLeast a meta.productsCount raised to the products listed (the data source counts fewer). meta.productsCount is null for a count of 0 with no product listed next to visits, a sales estimate or units sold, a count the data source has not made, as on the shop record (meta.nullReasons.productsCount not_measured; not_shopify off Shopify). productUrl is the product's page on the shop's own site, as in the shop record's catalog.bestSellers: the address the data source gives when it is on the shop's domain (or a subdomain of it) or its myshopify domain, else https://<domain>/products/<handle> when its handle is known, else null (never an address on another site); handle is null when it is no single part of an address. When the shop's own domains could not be read this time, every productUrl is null, with meta.partial true. createdAt, publishedAt and updatedAt are UTC: the data source writes the shop's own clock, put in UTC with the shop's offset from UTC (meta.shopUtcOffset, such as -08:00, read from a product its shop details list too); when no offset can be read, the three are null (nullReasons local_time) and createdAtLocal, publishedAtLocal and updatedAtLocal give the shop's clock, without a zone. A best seller listed by the shop details only has their createdAt; its publishedAt and updatedAt are null (not_reported: the data source's are copies of the creation time). lists names the lists a product is in (bestSellers, newest) and listPosition its place among the best-selling products (1 to 100).
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
limit Results per page, 1-100 (default 32).
offset Results to skip.
sortBy Defaults to popularity (best sellers first). One of: popularity, price, createdAt.
order Sort direction: asc by default for popularity (best sellers first), desc for price and createdAt. One of: asc, desc.
snapshotDate A past day (YYYY-MM-DD): the products as the shop listed them then, unranked.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/products?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/similar

Shops similar to a shop id or domain. The shop itself and its own sites (the same name under another suffix or subdomain, the same myshopify domain, or one of its brand stores) are left out, and the page is filled from further down the list: offset and limit count the list without them, so pages never repeat or skip a shop. pagination.total is one total for every order and page: until the list is read to its end in some order, an estimate (pagination.totalEstimated true), the data source's count less the own sites the first read met; then the exact count. When the reads stop before the page fills (a list made mostly of the shop's own sites), the page holds what was found and meta.partial is true, with pagination.hasMore true: the next page reads on. similarityScore is null when the data source gives none. season, or seasonFrom and seasonTo, list the shops similar over a season (meta.season); filters, market and excludeShopIds narrow the full list. Each row's shop is the shop's search row with its extra (logo, Trustpilot, sales history; on the Free plan without its ad averages and TikTok and Google ad history), its createdAt a Shopify store's creation date (trackedSince for a site off Shopify), its catalog.bestSellers with handle, productUrl and rank. When the data source stops the list before its end, the page that reaches that point has meta.partial true and a warning.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
sortBy Defaults to relevance. One of: relevance, monthlyVisits, activeAds, growth30d, productsCount, createdAt.
order Sort direction (default desc). One of: desc, asc.
offset Results to skip.
limit Results per page, 1-100 (default 32).
season bfcm-YYYY: the shops similar over that Q4 season (November 1 to December 4).
seasonFrom First day of a season (YYYY-MM-DD).
seasonTo Last day of a season (YYYY-MM-DD).
filters Shop filters of the full list, as a JSON object, such as {"minMonthlyVisits": 1000000}.
market 2-letter ISO code of the market.
excludeShopIds Shops to leave out, comma-separated.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/similar?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/advertisers

Advertiser pages linked to a shop. Each page's live and total ads, likes, profile, creation date and ad library link. With the shop's page selector each page also carries shopAds and landingPages, and meta.domains lists the shop's domains with their ads, pages and landing pages. A landing page on the shop's own domain (or a subdomain of it) is toShop true, and when the data source's domains leave that domain out, it comes first with its pages' landing pages on it (fromLandingPages true: its counts are those of the landing pages listed, a lower bound; isShopify null). A page's shopAds is never fewer than the live ads of its landing pages that are toShop: a count of the data source's raised to them is marked shopAdsAtLeast true (a lower bound). With the selector each page also carries logoUrl (its picture), profileUrl (the ad overview's, else the selector's) and moreLandingPages (count and ads of its landing pages past those listed), and each domain landingPagesCount and moreLandingPages. The selector's further pages are read too, five reads at most.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
limit Results, 1-100 (default 100).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/advertisers" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/socials/history

Social follower history.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
period One point per day, week or month. One of: day, week, month.
days How many days back, 7-365 (default 90).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/socials/history?days=90" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/sales/history

Estimated sales history. The data source estimates sales daily: period=week has one point per week (its Monday), period=month one per month, each the bucket's last daily estimate. An estimate of zero next to units sold is null.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
period One point per day, week or month. One of: day, week, month.
days How many days back, 7-365 (default 90).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/sales/history?days=90" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/socials

Social accounts and followers of a shop.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/socials" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/tiktok

Shop TikTok overview.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/tiktok" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/apps

Shopify apps a shop uses.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/apps" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/pixels

Tracking pixels on a shop.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/pixels" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/stores

Other stores of the same brand.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/stores" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/media-mix

Ad format mix of a shop.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/media-mix" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/emails

Emails sent by a shop. The shop's emails of every campaign type (Marketing, Newsletter, Welcome and Abandoned Cart), newest first.
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/emails?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/compare

One figure of several shops side by side. The brand tracker's compare chart: each shop's value (googleLiveAds: the Google ads it runs, as the data source counts them; tiktokPosts: its TikTok posts; metaReach: its Meta reach) with its change (delta) when the data source gives one, in the order asked.
ParameterDescription
shopIdsrequired 1 to 10 shop ids or domains, comma-separated.
metricrequired The figure compared. One of: googleLiveAds, tiktokPosts, metaReach.
snapshotDate A past day (YYYY-MM-DD) instead of today.
curl "https://api.sellwinners.com/v1/shops/compare?shopIds=allbirds.com%2Con.com" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tools/shopify-apps

Shopify apps a store uses, by its address. Any store, tracked or not: each app's name, icon and a link to find it on the Shopify App Store. The store is read at its domain without www. (meta.url).
ParameterDescription
urlrequired The store's address.
curl "https://api.sellwinners.com/v1/tools/shopify-apps?url=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tools/shopify-theme

Whether a store runs on Shopify, and its theme. isShopify, theme and isHeadless (a storefront built apart from Shopify's themes). Any store, tracked or not, read at its domain without www. (url).
ParameterDescription
urlrequired The store's address.
curl "https://api.sellwinners.com/v1/tools/shopify-theme?url=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/feed

A shop's latest ads and emails. The newest Meta ads, Google ads, TikTok ads and emails of the shop (metaAds, googleAds, tiktok, emails), each with its total (totalExact false for a lower bound), as their searches show them. metaAds are the shop's own, as its ad searches list them: every ad of its own pages, and the ads of its other pages (creators, publishers and partners, who run other brands' ads too) that link to the shop or to a site on its domain; when such another ad is left out, metaAds.total counts the shop's own ads listed.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
snapshotDate A past day (YYYY-MM-DD) instead of today.
since Count the totals from this day (YYYY-MM-DD).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/feed" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/q4-season

A shop's Q4 season, day by day. November 1 to December 4 of the year, for the shop's main Facebook page (or advertiserIds): the Meta ads live and launched each day (those about Black Friday too), their reach, the creatives, landing pages and products launched, the season's sales (operations) and its best creatives, winners (each sale's key and its creatives), landing pages (url as the season's landing pages write it) and products as the data source lists them, empty when it lists none (the season's creatives lists every creative).
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
year The season's year (default the latest begun).
euOnly Only the ads shown in the EU and the UK. One of: true, false.
advertiserIds Only these Facebook pages of the shop, comma-separated.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/q4-season" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/q4-season/landing-pages

Landing pages of a shop's Q4 season. The season's landing pages by the date each appeared: url, ads, screenshotUrl, isBlackFriday and blackFridayStartedAt. meta.total counts them all.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
year The season's year (default the latest begun).
euOnly Only the ads shown in the EU and the UK. One of: true, false.
advertiserIds Only these Facebook pages of the shop, comma-separated.
from First day (default November 1).
to Last day (default December 4).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/q4-season/landing-pages" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/q4-season/creatives

Creatives of a shop's Q4 season. The season's creatives by the date each was launched: adId, hook, thumbnailUrl, mediaType, reach and isActive. meta.total counts them all.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
year The season's year (default the latest begun).
euOnly Only the ads shown in the EU and the UK. One of: true, false.
advertiserIds Only these Facebook pages of the shop, comma-separated.
from First day (default November 1).
to Last day (default December 4).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/q4-season/creatives" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/ad-texts

A shop's hooks, transcripts, headlines or ad copies. The texts the ads of the shop's own pages use, or of those of its pages advertiserIds names. A hook, a headline and a transcript (fullText, with its hook) have usageCount, longestRunning, euReach, firstUsedAt, lastUsedAt and sampleAd; an ad copy has adCopy, usageCount, longestRunning and hash (the adCopyHashes filter of an ad search takes it).
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
kindrequired The texts to list. One of: hook, transcript, headline, ad-copy.
advertiserIds Only these Facebook pages of the shop, comma-separated.
euOnly Over the ads shown in the EU or the UK only.
sortBy The order (default usageCount); an ad copy takes usageCount. One of: usageCount, longestRunning, totalImpressions, firstUsedAt, lastUsedAt.
order Descending by default. One of: desc, asc.
timePeriod The ads counted (default live); not with ad-copy. One of: live, last24h, last3d, last7d, last30d, last3m, last6m, last1y.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/ad-texts?kind=hook&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/landing-pages

A shop's landing pages. The landing pages of the shop's Meta ads, the most used first, of all its pages or of those advertiserIds names: url, displayUrl, path, status, activeAds, ads (recorded), longestRunningDays, activeSince, screenshotUrl, reach (the EU and UK reach of its ads, null with nullReasons.reach), shareOfAds (a fraction), targetedCountries, snapshots (the days it was captured) and trend (its live ads day by day, its latest 30 days). meta.total counts them all.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
advertiserIds Only these Facebook pages of the shop, comma-separated.
euOnly Count the ads shown in the EU or the UK only.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/landing-pages" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/landing-pages/detail

One landing page of a shop's ads. landingPage (its ads, live ads, shareOfAds, best rank, reach, countries, technologies and snapshots, the days it was captured), linkedAds (the newest ads linking to it, as ad searches show them), linkedAdsTotal, shopActiveAds, linkedProducts, screenshots and snapshotDates. shareOfAds is linkedAdsTotal out of shopActiveAds (a fraction), null when the shop counts fewer. reach is the EU and UK reach of its ads, null when none is counted (nullReasons.reach no_eu_reach). meta.partial, with a warning, when some linked ads could not be read in full.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
urlrequired The landing page's address.
limit Linked ads, 1-50 (default 12).
snapshotDate One of its snapshotDates (YYYY-MM-DD): its screenshots as they were then.
euOnly Its figures over the ads shown in the EU or the UK only.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/landing-pages/detail?url=https%3A//www.allbirds.com/" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/advertisers/{advertiserId}/landing-pages

Landing pages of one of a shop's Facebook pages. The pages the advertiser's ads send people to, the most used first: url, ads, activeAds and toShop (the shop's own site: one of the sites the data source counts as the shop's, or on the shop's own domain or a subdomain of it).
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
advertiserIdrequired Facebook page id of an advertiser or ad.
limit Results, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/advertisers/ADVERTISER_ID/landing-pages" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/ad-ranking

A shop's Meta ads ranked over a window. The shop's ads as ad searches show them, ranked over the window (meta.from, meta.to): those of its own pages (its main page and its official pages named like it: the creators, publishers and partners among its pages run other brands' ads too), or of those of its pages advertiserIds names (meta.advertiserIds). Each row's rank.rankDelta and rank.improvementPct are its change over the window, as the rank series gives them: its end rank minus its start rank in the window, the series' start and end (negative when it moved up, as in every ad), and the fraction of its start rank gained.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
mode best-rank (default): the best rank each reached; rank-delta: the places each gained. One of: best-rank, rank-delta.
days The window, up to yesterday (default 7). One of: 7, 14, 30.
advertiserIds Only these Facebook pages of the shop, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 24).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/ad-ranking?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/shops/{shopId}/ad-ranking/query

A shop's Meta ads ranked, with filters. As GET /v1/shops/{shopId}/ad-ranking: mode, days, advertiserIds, page and limit in the body, with euOnly (the ads shown in the EU or the UK, ranked among those) and the filters of POST /v1/ads/query.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
curl -X POST "https://api.sellwinners.com/v1/shops/allbirds.com/ad-ranking/query" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/ad-ranking/series

The daily rank of some of a shop's ads. Each ad's rank among the live ads of the ranking's pages (the shop's own pages, or those advertiserIds names) on the first and last day (start, end), observedDays, rankDelta (end.rank minus start.rank: negative when the ad moved up, as in its ranking row and every ad), improvementPct (the fraction of start.rank gained) and every day's rank (points).
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
adIdsrequired Up to 24 ad ids, comma-separated.
days The window, up to yesterday (default 7). One of: 7, 14, 30.
advertiserIds Only these Facebook pages of the shop, comma-separated.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/ad-ranking/series" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/creative-testing

A shop's creative tests, day by day. The shop's Meta ads grouped by launch day, newest first: totalAds, activeAds, longRunningActiveAds (running a week or more after launch), isWinner, wasWinner, daysRunning and reach (min, avg, max, total), and asOf, to pass to the day's ads; the ads of its own pages (its main page and its official pages named like it), or of those of its pages advertiserIds names.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
mediaType Defaults to all. One of: all, image, video.
status One of: all, active, inactive.
keywords Words in the ads, comma-separated.
keywordMode One of: any, all.
advertiserIds Only these Facebook pages of the shop, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/creative-testing?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/creative-testing/{date}

The ads of one of a shop's creative tests. batch (the day's figures) and ads (the ads launched that day, as ad searches show them), of the shop's own pages or those advertiserIds names.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
daterequired A day, as YYYY-MM-DD.
mediaType Defaults to all. One of: all, image, video.
status One of: all, active, inactive.
keywords Words in the ads, comma-separated.
keywordMode One of: any, all.
advertiserIds Only these Facebook pages of the shop, comma-separated.
asOf The asOf of the day's creative-test row (default the latest).
limit Ads, 1-50 (default 50).
curl "https://api.sellwinners.com/v1/shops/allbirds.com/creative-testing/2026-10-19" \
  -H "X-API-Key: YOUR_API_KEY"

Market

The whole market's daily totals, and its Q4 season.

GET/v1/market/overview

The whole market, day by day. Each day: metaActiveAds, metaNewAds, metaReach (the EU and UK reach the day's Meta ads gained) and emails. 366 days at most. The totals run a few weeks behind: meta.latestDate is the last day with totals.
ParameterDescription
from First day (YYYY-MM-DD; default 365 days before to).
to Last day (YYYY-MM-DD; default today).
curl "https://api.sellwinners.com/v1/market/overview" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/market/q4-overview

The whole market over a Q4 season, day by day. November 1 to December 4 (from and to may be any days inside it): bfcmContentIndex, shopsFirstBfcmMention, metaNewAds, metaNewBfcmAds, metaActiveBfcmAds, metaBfcmAdvertisers, metaBfcmReach, emails and bfcmEmails, day by day.
ParameterDescription
year The season's year (default the latest begun).
from First day (default November 1).
to Last day (default December 4).
curl "https://api.sellwinners.com/v1/market/q4-overview" \
  -H "X-API-Key: YOUR_API_KEY"

Meta Ads

Facebook and Instagram ad creatives with media, reach and rank.

GET/v1/ads

Search Meta ads. A search returns one ad per brand unless maxAdsPerBrand is raised (0: no cap); trackedPages (Facebook page ids) and websiteIds (shop ids) narrow it to those brands, with all their ads: a shop's are its own (every ad of its main page and of its official pages named like it, and the ads of its other pages, creators, publishers and partners who ran its ads, that link to the shop or to a site on its domain; trackedPages narrows the search to the pages it names; until the list is read to its end, its pagination.total is then the ads of the shop's own pages searched, an estimate, pagination.totalEstimated true, as the ads of its other pages that link to it add to them, or null when the search names none of its own pages). sortBy=longestRunning takes order=desc only; each batch of ads read from the data source is put in order of daysRunning (its own order can be a day off); sortBy=adRank lists the best rank (1) first, whatever the order. metrics.reach is EU reach: null for an ad not shown in the EU or the UK, with its spend (nullReasons eu_uk_only), and for an EU ad whose reach is not counted yet (not_measured). The ad's targeting decides: an ad that targets no EU or UK country is eu_uk_only, one that targets one, or whose targeting is not known yet, not_measured in its first 7 days and not_reported after. media.type is carousel for an ad of more than one image or video (the thumbnails of its videos aside). advertiser.instagramFollowers is null for a page with no Instagram account or none the data source knows. extra.startIsFloor marks an ad started on January 1, 2018, the first day of the data source's Meta ad dates: it may be older. metrics.estimatedSpend keeps two decimals under 10 USD (1.26) and is in whole dollars from 10 USD up. A row's reach is the ad index's reading, which can be a day behind the ad's record (GET /v1/ads/{adId}). A row's metrics.reachDelta1d, reachDelta7d and reachDelta30d are null beside a known reach when the data source lists none (nullReasons not_measured), except over a window the ad started in, where it gained all the reach its row reads; the ad's record reads them from its reach history. A row's rank.lastRank is the last rank of an ad not ranked now (rank.currentTotal and rank.lastRankedAt are null on rows: the ad's record has them); metrics.reachGrowth7d, the EU reach growth over 7 days as a fraction, is null beside a known reach when the data source lists none (nullReasons not_measured); advertiser.countryShares is where the page's ads run, each country with its share of the page's ads as a fraction (an ad targets several countries, so the shares can add up to more than 1). growthRank takes rising, stable or falling; ageRanges and excludeAgeRanges 13-17, 18-24, 25-34, 35-44, 45-54, 55-64 and 65+; minPageAdsLaunched and maxPageAdsLaunched count the ads the page launched over pageAdsLaunchedPeriod (yesterday, last7d, last14d, last30d, last90d); adsTimePeriod takes last7d, last14d or last30d; reachPeriod, spendPeriod, reachPerPagePeriod and spendPerPagePeriod last24h, last7d or last30d (no period: all time); shopifyStoresOnly keeps the ads of Shopify stores. Growth ranges are percentages over 30 days; adReachGrowth also takes min7 and max7 (7 days) and adsGrowth min90 and max90 (90 days).
Named filters 114extra query parameters
adCopyHashesadCountriesadLanguageadRankBasisadRankModeadReachGrowthadsGrowthadsTimePeriodageRangescategoryIdscountriescpmcreatedAftercreatedBeforecreationCountryctaexcludeAdLanguagesexcludeAgeRangesexcludeFormatsexcludePixelsexcludeShopifyAppsexcludeThemesformatsgrowthRankhideDecliningRankAdshideLowReachhideNonEuUkAdshideSavedAdslandingPageslastSeenAfterlastSeenBeforelinkedDomainmainCountriesmarketmaxAdOrdermaxAdRankValuemaxAdReachGrowthmaxAdsmaxAdsPerBrandmaxAgemaxBestSellerPricemaxDatemaxDaysRunningmaxDescriptionLengthmaxDuplicatesmaxFacebookLikesmaxFbPageCreationDatemaxInstagramFollowersmaxLastSeenDatemaxMonthlyVisitsmaxPageAdsGrowthmaxPageAdsLaunchedmaxPageReachGrowthmaxProductsmaxProductsCountmaxReachmaxReachPerPagemaxSpendmaxSpendPerPagemaxTrafficmaxTrafficGrowthmaxVideoDurationmediaTypemediaTypesminAdOrderminAdReachGrowthminAdsminAgeminBestSellerPriceminDateminDaysRunningminDescriptionLengthminDuplicatesminFacebookLikesminFbPageCreationDateminInstagramFollowersminLastSeenDateminMonthlyVisitsminPageAdsGrowthminPageAdsLaunchedminPageReachGrowthminProductsminProductsCountminRankDeltaminReachminReachPerPageminSpendminSpendPerPageminTrafficminTrafficGrowthminVideoDurationpageAdsLaunchedPeriodpageReachGrowthpartnerIdspartnerspixelsplatformplatformsrankDeltaWindowreachPerPagePeriodreachPeriodsexshopCreatedAftershopCreatedBeforeshopifyAppsshopifyStoresOnlyspendPerPagePeriodspendPeriodstatustechnologiesthemestrackedPagestrafficGrowthwebsiteIds
ParameterDescription
search Words in the ad copy, brand or landing page.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
country 2-letter ISO country code.
active Running (true) or stopped (false) ads. One of: true, false.
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, reach, reachGrowth7d, reachDelta7d, longestRunning, duplicates, spend, adRank, rankDelta7d, rankDelta14d, rankDelta30d, createdAt, relevanceScore, mostDuplicates, adOrder.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/ads?search=skincare&country=US&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/ads/query

Search Meta ads with advanced filters. A search returns one ad per brand unless maxAdsPerBrand is raised (0: no cap); trackedPages (Facebook page ids) and websiteIds (shop ids) narrow it to those brands, with all their ads: a shop's are its own (every ad of its main page and of its official pages named like it, and the ads of its other pages, creators, publishers and partners who ran its ads, that link to the shop or to a site on its domain; trackedPages narrows the search to the pages it names; until the list is read to its end, its pagination.total is then the ads of the shop's own pages searched, an estimate, pagination.totalEstimated true, as the ads of its other pages that link to it add to them, or null when the search names none of its own pages). sortBy=longestRunning takes order=desc only; each batch of ads read from the data source is put in order of daysRunning (its own order can be a day off); sortBy=adRank lists the best rank (1) first, whatever the order. metrics.reach is EU reach: null for an ad not shown in the EU or the UK, with its spend (nullReasons eu_uk_only), and for an EU ad whose reach is not counted yet (not_measured). The ad's targeting decides: an ad that targets no EU or UK country is eu_uk_only, one that targets one, or whose targeting is not known yet, not_measured in its first 7 days and not_reported after. media.type is carousel for an ad of more than one image or video (the thumbnails of its videos aside). advertiser.instagramFollowers is null for a page with no Instagram account or none the data source knows. extra.startIsFloor marks an ad started on January 1, 2018, the first day of the data source's Meta ad dates: it may be older. metrics.estimatedSpend keeps two decimals under 10 USD (1.26) and is in whole dollars from 10 USD up. A row's reach is the ad index's reading, which can be a day behind the ad's record (GET /v1/ads/{adId}). A row's metrics.reachDelta1d, reachDelta7d and reachDelta30d are null beside a known reach when the data source lists none (nullReasons not_measured), except over a window the ad started in, where it gained all the reach its row reads; the ad's record reads them from its reach history. A row's rank.lastRank is the last rank of an ad not ranked now (rank.currentTotal and rank.lastRankedAt are null on rows: the ad's record has them); metrics.reachGrowth7d, the EU reach growth over 7 days as a fraction, is null beside a known reach when the data source lists none (nullReasons not_measured); advertiser.countryShares is where the page's ads run, each country with its share of the page's ads as a fraction (an ad targets several countries, so the shares can add up to more than 1). growthRank takes rising, stable or falling; ageRanges and excludeAgeRanges 13-17, 18-24, 25-34, 35-44, 45-54, 55-64 and 65+; minPageAdsLaunched and maxPageAdsLaunched count the ads the page launched over pageAdsLaunchedPeriod (yesterday, last7d, last14d, last30d, last90d); adsTimePeriod takes last7d, last14d or last30d; reachPeriod, spendPeriod, reachPerPagePeriod and spendPerPagePeriod last24h, last7d or last30d (no period: all time); shopifyStoresOnly keeps the ads of Shopify stores. Growth ranges are percentages over 30 days; adReachGrowth also takes min7 and max7 (7 days) and adsGrowth min90 and max90 (90 days).
Named filters 114top-level body fields
adCopyHashesadCountriesadLanguageadRankBasisadRankModeadReachGrowthadsGrowthadsTimePeriodageRangescategoryIdscountriescpmcreatedAftercreatedBeforecreationCountryctaexcludeAdLanguagesexcludeAgeRangesexcludeFormatsexcludePixelsexcludeShopifyAppsexcludeThemesformatsgrowthRankhideDecliningRankAdshideLowReachhideNonEuUkAdshideSavedAdslandingPageslastSeenAfterlastSeenBeforelinkedDomainmainCountriesmarketmaxAdOrdermaxAdRankValuemaxAdReachGrowthmaxAdsmaxAdsPerBrandmaxAgemaxBestSellerPricemaxDatemaxDaysRunningmaxDescriptionLengthmaxDuplicatesmaxFacebookLikesmaxFbPageCreationDatemaxInstagramFollowersmaxLastSeenDatemaxMonthlyVisitsmaxPageAdsGrowthmaxPageAdsLaunchedmaxPageReachGrowthmaxProductsmaxProductsCountmaxReachmaxReachPerPagemaxSpendmaxSpendPerPagemaxTrafficmaxTrafficGrowthmaxVideoDurationmediaTypemediaTypesminAdOrderminAdReachGrowthminAdsminAgeminBestSellerPriceminDateminDaysRunningminDescriptionLengthminDuplicatesminFacebookLikesminFbPageCreationDateminInstagramFollowersminLastSeenDateminMonthlyVisitsminPageAdsGrowthminPageAdsLaunchedminPageReachGrowthminProductsminProductsCountminRankDeltaminReachminReachPerPageminSpendminSpendPerPageminTrafficminTrafficGrowthminVideoDurationpageAdsLaunchedPeriodpageReachGrowthpartnerIdspartnerspixelsplatformplatformsrankDeltaWindowreachPerPagePeriodreachPeriodsexshopCreatedAftershopCreatedBeforeshopifyAppsshopifyStoresOnlyspendPerPagePeriodspendPeriodstatustechnologiesthemestrackedPagestrafficGrowthwebsiteIds
curl -X POST "https://api.sellwinners.com/v1/ads/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "mainCountries": ["US"], "mediaType": "video", "minDaysRunning": 14, "page": 1, "query": "skincare", "sortBy": "reach", "status": "active"}'

GET/v1/ads/{adId}

One Meta ad by id. The full record: creative, copy, transcript and hook, spend, rank, linked shop and page history. metrics.reach is the ad's EU reach, the latest the data source reports (the record, its reach and spend figures, its reach and spend histories), and metrics.estimatedSpend the spend of that reach (two decimals under 10 USD, whole dollars from 10 USD up); both are null for an ad not shown in the EU or the UK (nullReasons eu_uk_only: reach is reported for those only), and for an EU ad whose reach is not counted yet (not_measured). The ad's targeting decides: an ad that targets no EU or UK country is eu_uk_only, one that targets one, or whose targeting is not known yet, not_measured in its first 7 days and not_reported after. metrics.reachDelta1d, reachDelta7d and reachDelta30d are the reach gained over those days, by date, while the ad's reach history is current (its last reading at most 2 days old), else null; an ad started inside the window gained all its reach in it, and a gain below that of fewer days is null; a gain that is null beside a known reach has nullReasons not_measured. Its reach and spend histories are read as one series, one reading a day (the higher on a day both read), the deltas and the reach chart too; a record's reach more than twice the last reading of a series that runs to the ad's last day is not this ad's alone, so that reading and its spend are taken, and extra.recordReach holds the record's (the figure ad listings show) and extra.recordSpend the spend of it. media and extra.medias are the ad's images and videos as its search row lists them: media.type is carousel for an ad of more than one; media.mediaUrl and thumbnailUrl fall back on its first listed file when the record has none. advertiser.reach30d is the page's EU reach over 30 days, as advertiser lists show it, and advertiser.totalReach is the page details' EU reach when the record has none, never below the last reading of pageAnalytics.reachHistory (extra.pageRecordReach then holds the record's total, the one advertiser lists show), and that reading while it is current (at most 2 days old), so the figure and the chart agree; null for a page with no reach reported. extra.advertiserTotalAds is the page's total ads (the record's, else its search row's or its advertiser row's; null with nullReasons not_measured when none counts them). pageAnalytics holds the page's EU reach so far (reachHistory; impressionsHistory is the same series), its Facebook likes and Instagram followers, day by day, from the day the page was created, without the readings the data source missed (a 0 of likes or followers between two readings above 0, or of a day it missed the page's other readings); it is null with meta.partial when the page's history could not be read. extra.spendHistory starts on the day the ad started, its spendUsd with two decimals under 10 USD as metrics.estimatedSpend. extra.reachScope and extra.pageReachScope say where most of the ad's reach (by extra.reachByCountry) and of its page's was seen: eu_uk, or outside_eu_uk (the data source reports the reach of some ads shown elsewhere too). shops holds the ad's shop when the record names it, by id or by domain; its traffic is null when the traffic data has not measured the site (nullReasons shops.traffic not_measured). extra.startIsFloor marks an ad started on January 1, 2018, the first day of the data source's Meta ad dates: it may be older. audience.gender, ageMin and ageMax and metrics.aggregatedReach are always null: the data source does not report them for one ad. For an ad whose website is not a shop (a messaging or social site, an app store, a redirect), shops is empty and extra.nonShopSite names the site; in ad listings extra.shop is left out then. rank.currentRank is the ad's rank in its rank history and rank.currentTotal the number of ads it is ranked among there (null with nullReasons not_reported when the data source gives none); extra.rankPopulation is the page's live ads the data source counts, not the ranked pool. rank.rankDelta and rank.improvementPct are the move over 7 days, as on list rows: the current rank minus the rank the history read 7 days before its last day (or the day before that), else the record's own 7-day figure, else null (nullReasons not_reported); negative means it moved up. rank.rankDelta14d is the move since rank.rankDelta14dSince (14 days back, later for an ad ranked for less) and rank.rankDelta3d the move since rank.rankDelta3dSince. An ad not ranked now has rank.lastRank, the last rank it held, and rank.lastRankedAt, the day of it (null when not known). metrics.reachGrowth7d is the EU reach growth over 7 days as a fraction (0.0075 is 0.75%), null while the reach history is not current (as the reach gained) and null beside a known reach with nullReasons not_measured. advertiser.estimatedSpend is the page's estimated spend so far and advertiser.avgDailySpend14d its average daily spend over 14 days (USD), both null with the reason of advertiser.totalReach when that one has one (eu_uk_only). advertiser.countryShares is where the page's ads run: each country with its share of the page's ads, a fraction (an ad targets several countries, so the shares can add up to more than 1), from the ad's search row when the record lists none. shops also holds the shop's logoUrl, trafficGrowth30d (a fraction, only beside monthly visits above 0, else null with nullReasons shops.trafficGrowth30d not_measured), trustpilot (rating and reviewCount, no rating beside 0 reviews; null when the data source has neither), productsCount (productsCountCapped at the data source's ceiling of 25,001: 25,000 or more) and linkedAds (the ads linking to the shop).
ParameterDescription
adIdrequired Ad id from an ad search.
curl "https://api.sellwinners.com/v1/ads/AD_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/ads/{adId}/reach-history

Daily reach of one ad.
ParameterDescription
adIdrequired Ad id from an ad search.
limit Most recent days, 1-365 (default 365).
curl "https://api.sellwinners.com/v1/ads/AD_ID/reach-history?limit=30" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/ads/{adId}/media-url

Download URL of one ad's creative.
ParameterDescription
adIdrequired Ad id from an ad search.
curl "https://api.sellwinners.com/v1/ads/AD_ID/media-url" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/ads/facets/landing-pages

Landing pages used by a shop's or pages' ads. Send exactly one of scopeDomain or scopeTrackedPages. With scopeTrackedPages a landing page's activeAdsCount is null (only a shop counts its live ads), so status must be all or left out (active or inactive is a 400); a page that could not be read sets meta.partial and meta.warnings.
ParameterDescription
scopeDomain A shop domain.
scopeTrackedPages Up to 20 Facebook page ids, comma-separated.
status Pages with running ads, without, or all (default all). One of: active, inactive, all.
limit Results, 1-100 (default 100).
snapshotDate A past day (YYYY-MM-DD), with scopeDomain: the shop's landing pages as they were then.
curl "https://api.sellwinners.com/v1/ads/facets/landing-pages?scopeDomain=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/ads/facets/ad-copies

Ad texts of a shop's ads. The ad texts of the shop's own pages, or of those advertiserIds names, the most used first, for the adCopyHashes filter of an ad search: id (the text's hash), name (its first characters), adCopy (all of it) and usageCount. meta.total counts them all.
ParameterDescription
scopeDomainrequired The shop's domain or id.
limit Results, 1-100 (default 100).
advertiserIds Only these Facebook pages of the shop, comma-separated.
curl "https://api.sellwinners.com/v1/ads/facets/ad-copies?scopeDomain=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/ads/facets/partners

Partners of a shop's ads. The pages that run partnership ads with the shop's own pages, or with those advertiserIds names, those with the most live ads first, for the partnerIds filter of an ad search: id (the Facebook page id), name and usageCount (its live ads). meta.total counts them all.
ParameterDescription
scopeDomainrequired The shop's domain or id.
limit Results, 1-100 (default 100).
advertiserIds Only these Facebook pages of the shop, comma-separated.
curl "https://api.sellwinners.com/v1/ads/facets/partners?scopeDomain=allbirds.com" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/ads/{adId}/share

Create (or return) a public link to an ad. The answer carries a shareUrl: a web page anyone can open, without an API key.
ParameterDescription
adIdrequired Ad id from an ad search.
curl -X POST "https://api.sellwinners.com/v1/ads/AD_ID/share" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/ads/{adId}/share

Remove the public link to an ad.
ParameterDescription
adIdrequired Ad id from an ad search.
curl -X DELETE "https://api.sellwinners.com/v1/ads/AD_ID/share" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shared/ads/{token}

An ad behind a share link (no key needed). The same record the share page shows, as JSON.
ParameterDescription
tokenrequired Token at the end of a share link.
curl "https://api.sellwinners.com/v1/shared/ads/TOKEN" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/tools/ad-hooks

Write ad hooks for a product. Three short opening lines for an ad of your product. niche (2 to 80 characters) and product (2 to 100) are required; angle is pain (the default), curiosity, social_proof, transformation or urgency; platform meta (Facebook and Instagram), tiktok or both (the default); language en (the default) or fr. regenerate, the text of one hook to write again, answers one new hook. Each call is one generation, a regenerate too: there is no monthly limit, and a few a minute at most (429 rate_limited with Retry-After). meta.allowance is what is left. Answers are never cached; idempotencyKey (8 to 64 letters, digits, - or _) makes a request sent again within 2 minutes get the first answer without being counted again. Nothing you send and no hook is stored.
curl -X POST "https://api.sellwinners.com/v1/tools/ad-hooks" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"angle": "pain", "language": "en", "niche": "skincare", "platform": "both", "product": "Vitamin C serum"}'

GET/v1/tools/ad-hooks

Your ad hook allowance this month. allowance: limit (null: no monthly limit, as on paid plans), used, remaining, resetsAt, perMinute and perDay (null on paid plans); enabled, and the angles, platforms and languages the writer takes. Not counted toward your monthly requests.
curl "https://api.sellwinners.com/v1/tools/ad-hooks" \
  -H "X-API-Key: YOUR_API_KEY"

Google Ads

Google ad creatives.

GET/v1/google-ads

Search Google ads. Searches are ranked by relevance; sortBy applies when browsing without a search term. formats are text, image and video; networks are Search, YouTube, Shopping, Maps and Other. Each ad has media.type and media.format (text, image or video) and media.url, the ad's image (for a video ad, its thumbnail: there is no video file). transparencyUrl is the ad on Google's Ads Transparency Center, where a video ad plays (null without Google's ids for the ad). Excluded audience countries (excludeCountryCodes, audienceCountries.exclude) work only without included ones. hideNonEuUkAds keeps the ads shown in the EU or the UK. Growth ranges are percentages over 30 days. status is active only while Google shows the ad (unknown once it has not for more than 7 days), and status=active keeps the ads Google showed in those 7 days; status=inactive keeps the ads the data source marks stopped, so an unknown ad is under neither. daysRunning counts the days from firstSeenAt to lastSeenAt, both included, and minDaysRunning and maxDaysRunning keep the ads whose daysRunning is in range; extra.servedDays is the data source's own count, which goes on after an ad stops, so longestRunning is not a Google sort; sortBy=relevance with no search term lists the newest; sortBy=reach takes order=desc only. With status=active or a days-running bound, pagination.total is null, and a list where few ads match ends early (meta.partial). With status=active, sortBy=reach lists few ads: in reach order the first ads are mostly ones Google stopped showing, so sort by newest for the ads Google shows now (its warning says so). extra.startIsFloor marks an ad first seen on May 31, 2018, the first day of Google's ad data. audience.countries lists every country (a percentage only for one country). Google reports a reach for some of the ads shown in the EU only, often only as 10,000,000, the top of its scale (10 million or more): most ads have none, and nullReasons says why reach.value is null (not_reported: an ad shown in the EU that Google reports none for; eu_only: an ad shown elsewhere), except for a reach the plan leaves out. extra.networks is the data source's list of the ad's platforms. extra.shop.google holds the Google totals of the advertiser's website, without a 0 reach (never reported) and, when it counts no ad, without its 0 counts; extra.shop has no monthlyVisits for a site with no traffic data, and a trafficGrowth30d only beside visits above 0. network and extra.networks name a network search, youtube, shopping, maps, display or other (display since October 23, 2026: it read other before); network, the ad's main network, is never display, so networks=display is refused with a 400 that says so (the data source answers none for it). advertiser.transparencyUrl is the advertiser's page on Google's Ads Transparency Center (null without Google's id for it) and advertiser.totalAds.all the website's ads on every platform. extra.categories names extra.categoryIds (id and name). extra.shop adds the website's countryCode, productsCount, followersBy (facebook, instagram, tiktok), metaTotalAds and metaNewAds, and extra.shop.google the time its totals were read (recordedAt, UTC) and the bounds of each reach it keeps (totalReachLow, totalReachUp, weeklyReachLow, weeklyReachUp). meta.breakdown, read with the list's total (on the first page of a search; the pages after it reuse that total and carry none), gives the search's ads by status (the data source's active flag, as liveAds counts, not status), by format (text, image, video), by servedDays bucket (the days served, which go on after an ad stops), by country (the first 10) and by network. remarketing and interestTargeting keep the ads that target it (true) or do not (false); minAdvertiserReach and maxAdvertiserReach bound the EU reach of the advertiser behind the ad; websiteIds narrows to one brand's shop; marketCountries, mainMarketCountries, excludeMarketCountries, creationCountries, excludeCreationCountries, the products count, best seller price and shop creation bounds, and shopifyAppIds, themeIds and pixelIds (with their exclude names, ids from /v1/facets/*) filter the shop behind the ad.
Named filters 41extra query parameters
audienceCountriescategoryIdscountriescreationCountriesexcludeCountryCodesexcludeCreationCountriesexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdsexcludeThemeIdsformatshideNonEuUkAdsinterestTargetingmainMarketCountriesmarketCountriesmaxAdvertiserReachmaxBestSellerPricemaxDaysRunningmaxProductsCountmaxReachmaxTrafficmaxTrafficGrowthminAdvertiserReachminBestSellerPriceminDaysRunningminProductsCountminReachminTrafficminTrafficGrowthnetworkspixelIdspublishedAfterpublishedBeforeremarketingshopCreatedAftershopCreatedBeforeshopifyAppIdsstatusthemeIdstrafficGrowthwebsiteIds
ParameterDescription
search
country 2-letter ISO country code.
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, reach.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/google-ads?search=running%20shoes&country=US&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/google-ads/query

Search Google ads with filters. formats are text, image and video; networks are Search, YouTube, Shopping, Maps and Other. Each ad has media.type and media.format (text, image or video) and media.url, the ad's image (for a video ad, its thumbnail: there is no video file). transparencyUrl is the ad on Google's Ads Transparency Center, where a video ad plays (null without Google's ids for the ad). Excluded audience countries (excludeCountryCodes, audienceCountries.exclude) work only without included ones. hideNonEuUkAds keeps the ads shown in the EU or the UK. Growth ranges are percentages over 30 days. status is active only while Google shows the ad (unknown once it has not for more than 7 days), and status=active keeps the ads Google showed in those 7 days; status=inactive keeps the ads the data source marks stopped, so an unknown ad is under neither. daysRunning counts the days from firstSeenAt to lastSeenAt, both included, and minDaysRunning and maxDaysRunning keep the ads whose daysRunning is in range; extra.servedDays is the data source's own count, which goes on after an ad stops, so longestRunning is not a Google sort; sortBy=relevance with no search term lists the newest; sortBy=reach takes order=desc only. With status=active or a days-running bound, pagination.total is null, and a list where few ads match ends early (meta.partial). With status=active, sortBy=reach lists few ads: in reach order the first ads are mostly ones Google stopped showing, so sort by newest for the ads Google shows now (its warning says so). extra.startIsFloor marks an ad first seen on May 31, 2018, the first day of Google's ad data. audience.countries lists every country (a percentage only for one country). Google reports a reach for some of the ads shown in the EU only, often only as 10,000,000, the top of its scale (10 million or more): most ads have none, and nullReasons says why reach.value is null (not_reported: an ad shown in the EU that Google reports none for; eu_only: an ad shown elsewhere), except for a reach the plan leaves out. extra.networks is the data source's list of the ad's platforms. extra.shop.google holds the Google totals of the advertiser's website, without a 0 reach (never reported) and, when it counts no ad, without its 0 counts; extra.shop has no monthlyVisits for a site with no traffic data, and a trafficGrowth30d only beside visits above 0. network and extra.networks name a network search, youtube, shopping, maps, display or other (display since October 23, 2026: it read other before); network, the ad's main network, is never display, so networks=display is refused with a 400 that says so (the data source answers none for it). advertiser.transparencyUrl is the advertiser's page on Google's Ads Transparency Center (null without Google's id for it) and advertiser.totalAds.all the website's ads on every platform. extra.categories names extra.categoryIds (id and name). extra.shop adds the website's countryCode, productsCount, followersBy (facebook, instagram, tiktok), metaTotalAds and metaNewAds, and extra.shop.google the time its totals were read (recordedAt, UTC) and the bounds of each reach it keeps (totalReachLow, totalReachUp, weeklyReachLow, weeklyReachUp). meta.breakdown, read with the list's total (on the first page of a search; the pages after it reuse that total and carry none), gives the search's ads by status (the data source's active flag, as liveAds counts, not status), by format (text, image, video), by servedDays bucket (the days served, which go on after an ad stops), by country (the first 10) and by network. remarketing and interestTargeting keep the ads that target it (true) or do not (false); minAdvertiserReach and maxAdvertiserReach bound the EU reach of the advertiser behind the ad; websiteIds narrows to one brand's shop; marketCountries, mainMarketCountries, excludeMarketCountries, creationCountries, excludeCreationCountries, the products count, best seller price and shop creation bounds, and shopifyAppIds, themeIds and pixelIds (with their exclude names, ids from /v1/facets/*) filter the shop behind the ad.
Named filters 41top-level body fields
audienceCountriescategoryIdscountriescreationCountriesexcludeCountryCodesexcludeCreationCountriesexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdsexcludeThemeIdsformatshideNonEuUkAdsinterestTargetingmainMarketCountriesmarketCountriesmaxAdvertiserReachmaxBestSellerPricemaxDaysRunningmaxProductsCountmaxReachmaxTrafficmaxTrafficGrowthminAdvertiserReachminBestSellerPriceminDaysRunningminProductsCountminReachminTrafficminTrafficGrowthnetworkspixelIdspublishedAfterpublishedBeforeremarketingshopCreatedAftershopCreatedBeforeshopifyAppIdsstatusthemeIdstrafficGrowthwebsiteIds
curl -X POST "https://api.sellwinners.com/v1/google-ads/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "page": 1, "query": "running shoes", "status": "active"}'

GET/v1/google-ads/{adId}

One Google ad by id. The fields of a search row, with reachHistory (its reach, day by day), estimatedSpend, platformMix and advertiserDetails (Google's advertiser account behind the ad: its ads live, new and in total, its reach week by week, its top countries by ads and by reach, its networks). reachHistory joins the readings of the ad's details and of its reach history by date (the reach history's on a day both read). platformMix lists the networks the ad ran on: platform (named as network is: search, youtube, shopping, maps, display or other), label (Google's name), share (a fraction) and percentage (0 to 100, as before). audience.countries gives each country's reachLowerBound and reachUpperBound beside its reach when the data source reads them. advertiserDetails.transparencyUrl is the advertiser's page on Google's Ads Transparency Center; advertiserDetails.snapshot holds its totals as a website's Google totals are read (a 0 reach and, with no ad counted, the 0 counts left out; recordedAt in UTC; the bounds of each reach kept), with estimatedSpend (USD) and cpm, the CPM it was made at (spendUsd and cpmUsd, their earlier names, stay for one release); advertiserDetails.platformMix names each network as platformMix does, with its label, ads, adsEu, share and percentage.
ParameterDescription
adIdrequired Google ad id from a Google ad search (google_CR...).
curl "https://api.sellwinners.com/v1/google-ads/AD_ID" \
  -H "X-API-Key: YOUR_API_KEY"

TikTok

TikTok ads and organic posts.

GET/v1/tiktok/library

Search TikTok ads and posts. Searches are ranked by relevance; sortBy applies when browsing without a search term. websiteId (a shop id) and domain narrow to one shop: its TikTok profiles, or for a shop with none, the posts linking to the shop or its stores on its domain. websiteIds in filters means the posts linking to those websites. mediaType is video or carousel; categories are the data source's category names, in any case; hashtags are taken with or without the #. Growth ranges are percentages over 30 days. In each row, metrics.engagementRate is (likes + comments + shares + saves) / views as a fraction (0.0513 is 5.13%), daysRunning the days since the post was published, and metrics.rank its rank among its creator's posts (1 is the best; rankPercent the same rank as a percent of the creator's posts). profile.followers is null when the data source has not counted them, and content.category is null for its catch-all All. metrics.views, and the likes and saves that read 0 beside them, are null with nullReasons not_measured (engagementRate too) when the data source sent 0 views next to likes, comments, shares or saves above 0, or fewer views than likes: it has not counted the post; sortBy=views or likes with order=asc lists the posts whose views are counted, from the first TikToks on: a view or more (minViews 1) and no fewer views than likes (the posts not counted are left out of these two orders only; pagination.total is an estimate, totalEstimated, until the list is read to its end). A row the data source sends with no views or likes (and no reason) takes the post's counts from its own record (GET /v1/tiktok/library/{itemId}) once that was read, all of one reading (metrics.countsFromPost true). sortBy=longestRunning starts at the first TikToks (August 31, 2016, 22:00 UTC): the data source's older rows are not real posts. publishedAt is UTC. The filters agree with it: publishedAfter and publishedBefore are UTC (a date alone is the start of its day, and publishedBefore lists the posts before it), and minDaysRunning and maxDaysRunning count from the UTC day, as daysRunning does. media.mediaUrl of a video post is its cover image (the same file as media.thumbnailUrl in most rows), never its video: media.videoUrl is the video. media.durationSec is null when the data source reads 0 (every carousel). profile.adsShare is the share of the profile's posts that are ads, a fraction (profile.percentAds is the same share as the data source's percent, 0 to 100). shop.monthlyVisits is null with nullReasons not_measured for a linked shop the data source reads 0 visits (and 0 growth) for, and shop.trafficGrowth30d is kept only beside visits above 0 (else null with nullReasons not_measured); shop.categories names shop.googleCategoryIds (id and name). sortBy=rank lists the best rank (1) first, whatever the order. GET /v1/tiktok/facets/categories lists the categories the categories filter takes. profileCreatedAfter and profileCreatedBefore bound the profile's creation, minProfileAdsShare and maxProfileAdsShare the percent of its posts that are ads (0 to 100), minProfilePosts and maxProfilePosts its posts; marketCountries, mainMarketCountries, excludeMarketCountries, creationCountries, excludeCreationCountries, minTraffic, maxTraffic, the products count, best seller price and shop creation bounds, and shopifyAppIds, themeIds and pixelIds (with their exclude names, ids from /v1/facets/*) filter the shop the post links to.
Named filters 58extra query parameters
categoriescategoryIdscountriescreationCountriesdomainexcludeCreationCountriesexcludeHashtagsexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdsexcludeThemeIdshandlehasShopLinkedhashtagsisPinnedlanguagesmainMarketCountriesmarketCountriesmaxBestSellerPricemaxDaysRunningmaxDurationmaxFollowersmaxProductsCountmaxProfileAdsSharemaxProfilePostsmaxProfileViewsmaxTrafficmaxTrafficGrowthmaxViewsmediaTypemediaTypesminBestSellerPriceminDaysRunningminDurationminFollowersminProductsCountminProfileAdsShareminProfilePostsminProfileViewsminTrafficminTrafficGrowthminViewspixelIdsprofileCreatedAfterprofileCreatedBeforepublishedAfterpublishedBeforeshopCreatedAftershopCreatedBeforeshopifyAppIdsthemeIdstiktokPageIdtiktokPageIdstrafficGrowthtypeupdatedAfterupdatedBeforewebsiteId
ParameterDescription
search
country 2-letter ISO country code.
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, views, likes, rank, longestRunning, daysRunning.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/tiktok/library?search=fitness&country=US&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/tiktok/library/query

Search TikTok ads and posts with filters. websiteId (a shop id) and domain narrow to one shop: its TikTok profiles, or for a shop with none, the posts linking to the shop or its stores on its domain. websiteIds in filters means the posts linking to those websites. mediaType is video or carousel; categories are the data source's category names, in any case; hashtags are taken with or without the #. Growth ranges are percentages over 30 days. In each row, metrics.engagementRate is (likes + comments + shares + saves) / views as a fraction (0.0513 is 5.13%), daysRunning the days since the post was published, and metrics.rank its rank among its creator's posts (1 is the best; rankPercent the same rank as a percent of the creator's posts). profile.followers is null when the data source has not counted them, and content.category is null for its catch-all All. metrics.views, and the likes and saves that read 0 beside them, are null with nullReasons not_measured (engagementRate too) when the data source sent 0 views next to likes, comments, shares or saves above 0, or fewer views than likes: it has not counted the post; sortBy=views or likes with order=asc lists the posts whose views are counted, from the first TikToks on: a view or more (minViews 1) and no fewer views than likes (the posts not counted are left out of these two orders only; pagination.total is an estimate, totalEstimated, until the list is read to its end). A row the data source sends with no views or likes (and no reason) takes the post's counts from its own record (GET /v1/tiktok/library/{itemId}) once that was read, all of one reading (metrics.countsFromPost true). sortBy=longestRunning starts at the first TikToks (August 31, 2016, 22:00 UTC): the data source's older rows are not real posts. publishedAt is UTC. The filters agree with it: publishedAfter and publishedBefore are UTC (a date alone is the start of its day, and publishedBefore lists the posts before it), and minDaysRunning and maxDaysRunning count from the UTC day, as daysRunning does. media.mediaUrl of a video post is its cover image (the same file as media.thumbnailUrl in most rows), never its video: media.videoUrl is the video. media.durationSec is null when the data source reads 0 (every carousel). profile.adsShare is the share of the profile's posts that are ads, a fraction (profile.percentAds is the same share as the data source's percent, 0 to 100). shop.monthlyVisits is null with nullReasons not_measured for a linked shop the data source reads 0 visits (and 0 growth) for, and shop.trafficGrowth30d is kept only beside visits above 0 (else null with nullReasons not_measured); shop.categories names shop.googleCategoryIds (id and name). sortBy=rank lists the best rank (1) first, whatever the order. GET /v1/tiktok/facets/categories lists the categories the categories filter takes. profileCreatedAfter and profileCreatedBefore bound the profile's creation, minProfileAdsShare and maxProfileAdsShare the percent of its posts that are ads (0 to 100), minProfilePosts and maxProfilePosts its posts; marketCountries, mainMarketCountries, excludeMarketCountries, creationCountries, excludeCreationCountries, minTraffic, maxTraffic, the products count, best seller price and shop creation bounds, and shopifyAppIds, themeIds and pixelIds (with their exclude names, ids from /v1/facets/*) filter the shop the post links to.
Named filters 58top-level body fields
categoriescategoryIdscountriescreationCountriesdomainexcludeCreationCountriesexcludeHashtagsexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdsexcludeThemeIdshandlehasShopLinkedhashtagsisPinnedlanguagesmainMarketCountriesmarketCountriesmaxBestSellerPricemaxDaysRunningmaxDurationmaxFollowersmaxProductsCountmaxProfileAdsSharemaxProfilePostsmaxProfileViewsmaxTrafficmaxTrafficGrowthmaxViewsmediaTypemediaTypesminBestSellerPriceminDaysRunningminDurationminFollowersminProductsCountminProfileAdsShareminProfilePostsminProfileViewsminTrafficminTrafficGrowthminViewspixelIdsprofileCreatedAfterprofileCreatedBeforepublishedAfterpublishedBeforeshopCreatedAftershopCreatedBeforeshopifyAppIdsthemeIdstiktokPageIdtiktokPageIdstrafficGrowthtypeupdatedAfterupdatedBeforewebsiteId
curl -X POST "https://api.sellwinners.com/v1/tiktok/library/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "minViews": 100000, "page": 1, "query": "fitness", "type": "ad"}'

GET/v1/tiktok/library/{itemId}

One TikTok item by id. profile.latestAds are the creator's latest ads by their cover (thumbnailUrl): a post's mediaUrl is its video when the data source lists one, else null (nullReasons mediaUrl not_reported; the post's own record carries its video). profile.latestAds are the profile's latest ads, as the data source lists them (profile.latestPosts, their earlier name, holds the same rows for one release). profile.followersDelta is null with nullReasons not_measured when profile.followers is null (the data source's change is from its 0). metrics.deltaRank3d, deltaRank7d, deltaRank14d, deltaRank30d and deltaRankPercent7d come from the post's search row when its record has none (the latest row a search showed, kept 30 days); deltaRank7d is null with nullReasons not_reported when neither has it. The fields of a search row read as GET /v1/tiktok/library describes them (media, profile.adsShare, the linked shop).
ParameterDescription
itemIdrequired Item id from a TikTok search.
curl "https://api.sellwinners.com/v1/tiktok/library/ITEM_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shop_id}/tiktok/library

TikTok items of one shop. The posts of the shop's TikTok profiles, or for a shop with none, the posts linking to the shop or its stores on its domain.
Named filters 58extra query parameters
categoriescategoryIdscountriescreationCountriesdomainexcludeCreationCountriesexcludeHashtagsexcludeMarketCountriesexcludePixelIdsexcludeShopifyAppIdsexcludeThemeIdshandlehasShopLinkedhashtagsisPinnedlanguagesmainMarketCountriesmarketCountriesmaxBestSellerPricemaxDaysRunningmaxDurationmaxFollowersmaxProductsCountmaxProfileAdsSharemaxProfilePostsmaxProfileViewsmaxTrafficmaxTrafficGrowthmaxViewsmediaTypemediaTypesminBestSellerPriceminDaysRunningminDurationminFollowersminProductsCountminProfileAdsShareminProfilePostsminProfileViewsminTrafficminTrafficGrowthminViewspixelIdsprofileCreatedAfterprofileCreatedBeforepublishedAfterpublishedBeforeshopCreatedAftershopCreatedBeforeshopifyAppIdsthemeIdstiktokPageIdtiktokPageIdstrafficGrowthtypeupdatedAfterupdatedBeforewebsiteId
ParameterDescription
shop_idrequired Shop id or domain, such as allbirds.com.
search
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, views, likes, rank, longestRunning, daysRunning.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/shops/SHOP_ID/tiktok/library?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

Media

Render-ready creatives: image and video URLs on our CDN.

GET/v1/media

Ad creatives as render-ready media. images are the ad's images and videos its videos, each with its posterUrl: the thumbnail of the same creative (its itemOrder), else the ad's thumbnailUrl; a video's thumbnail is never listed under images. A search returns one ad per brand unless maxAdsPerBrand is raised (0: no cap); trackedPages (Facebook page ids) and websiteIds (shop ids) narrow it to those brands, with all their ads: a shop's are its own (every ad of its main page and of its official pages named like it, and the ads of its other pages, creators, publishers and partners who ran its ads, that link to the shop or to a site on its domain; trackedPages narrows the search to the pages it names; until the list is read to its end, its pagination.total is then the ads of the shop's own pages searched, an estimate, pagination.totalEstimated true, as the ads of its other pages that link to it add to them, or null when the search names none of its own pages). sortBy=longestRunning takes order=desc only; each batch of ads read from the data source is put in order of daysRunning (its own order can be a day off); sortBy=adRank lists the best rank (1) first, whatever the order. metrics.reach is EU reach: null for an ad not shown in the EU or the UK, with its spend (nullReasons eu_uk_only), and for an EU ad whose reach is not counted yet (not_measured). The ad's targeting decides: an ad that targets no EU or UK country is eu_uk_only, one that targets one, or whose targeting is not known yet, not_measured in its first 7 days and not_reported after. media.type is carousel for an ad of more than one image or video (the thumbnails of its videos aside). advertiser.instagramFollowers is null for a page with no Instagram account or none the data source knows. extra.startIsFloor marks an ad started on January 1, 2018, the first day of the data source's Meta ad dates: it may be older. metrics.estimatedSpend keeps two decimals under 10 USD (1.26) and is in whole dollars from 10 USD up. A row's reach is the ad index's reading, which can be a day behind the ad's record (GET /v1/ads/{adId}). A row's metrics.reachDelta1d, reachDelta7d and reachDelta30d are null beside a known reach when the data source lists none (nullReasons not_measured), except over a window the ad started in, where it gained all the reach its row reads; the ad's record reads them from its reach history. A row's rank.lastRank is the last rank of an ad not ranked now (rank.currentTotal and rank.lastRankedAt are null on rows: the ad's record has them); metrics.reachGrowth7d, the EU reach growth over 7 days as a fraction, is null beside a known reach when the data source lists none (nullReasons not_measured); advertiser.countryShares is where the page's ads run, each country with its share of the page's ads as a fraction (an ad targets several countries, so the shares can add up to more than 1). growthRank takes rising, stable or falling; ageRanges and excludeAgeRanges 13-17, 18-24, 25-34, 35-44, 45-54, 55-64 and 65+; minPageAdsLaunched and maxPageAdsLaunched count the ads the page launched over pageAdsLaunchedPeriod (yesterday, last7d, last14d, last30d, last90d); adsTimePeriod takes last7d, last14d or last30d; reachPeriod, spendPeriod, reachPerPagePeriod and spendPerPagePeriod last24h, last7d or last30d (no period: all time); shopifyStoresOnly keeps the ads of Shopify stores. Growth ranges are percentages over 30 days; adReachGrowth also takes min7 and max7 (7 days) and adsGrowth min90 and max90 (90 days).
Named filters 114extra query parameters
adCopyHashesadCountriesadLanguageadRankBasisadRankModeadReachGrowthadsGrowthadsTimePeriodageRangescategoryIdscountriescpmcreatedAftercreatedBeforecreationCountryctaexcludeAdLanguagesexcludeAgeRangesexcludeFormatsexcludePixelsexcludeShopifyAppsexcludeThemesformatsgrowthRankhideDecliningRankAdshideLowReachhideNonEuUkAdshideSavedAdslandingPageslastSeenAfterlastSeenBeforelinkedDomainmainCountriesmarketmaxAdOrdermaxAdRankValuemaxAdReachGrowthmaxAdsmaxAdsPerBrandmaxAgemaxBestSellerPricemaxDatemaxDaysRunningmaxDescriptionLengthmaxDuplicatesmaxFacebookLikesmaxFbPageCreationDatemaxInstagramFollowersmaxLastSeenDatemaxMonthlyVisitsmaxPageAdsGrowthmaxPageAdsLaunchedmaxPageReachGrowthmaxProductsmaxProductsCountmaxReachmaxReachPerPagemaxSpendmaxSpendPerPagemaxTrafficmaxTrafficGrowthmaxVideoDurationmediaTypemediaTypesminAdOrderminAdReachGrowthminAdsminAgeminBestSellerPriceminDateminDaysRunningminDescriptionLengthminDuplicatesminFacebookLikesminFbPageCreationDateminInstagramFollowersminLastSeenDateminMonthlyVisitsminPageAdsGrowthminPageAdsLaunchedminPageReachGrowthminProductsminProductsCountminRankDeltaminReachminReachPerPageminSpendminSpendPerPageminTrafficminTrafficGrowthminVideoDurationpageAdsLaunchedPeriodpageReachGrowthpartnerIdspartnerspixelsplatformplatformsrankDeltaWindowreachPerPagePeriodreachPeriodsexshopCreatedAftershopCreatedBeforeshopifyAppsshopifyStoresOnlyspendPerPagePeriodspendPeriodstatustechnologiesthemestrackedPagestrafficGrowthwebsiteIds
ParameterDescription
search
mediaType Creative type. One of: image, video, dco, carousel, dpa.
country 2-letter ISO country code.
sortBy Defaults to relevance when searching, otherwise reach. One of: relevance, newest, reach, reachGrowth7d, reachDelta7d, longestRunning, duplicates, spend, adRank, rankDelta7d, rankDelta14d, rankDelta30d, createdAt, relevanceScore, mostDuplicates, adOrder.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/media?search=sneakers&country=US&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/media/query

Render-ready media with advanced filters. images are the ad's images and videos its videos, each with its posterUrl: the thumbnail of the same creative (its itemOrder), else the ad's thumbnailUrl; a video's thumbnail is never listed under images.
Named filters 114top-level body fields
adCopyHashesadCountriesadLanguageadRankBasisadRankModeadReachGrowthadsGrowthadsTimePeriodageRangescategoryIdscountriescpmcreatedAftercreatedBeforecreationCountryctaexcludeAdLanguagesexcludeAgeRangesexcludeFormatsexcludePixelsexcludeShopifyAppsexcludeThemesformatsgrowthRankhideDecliningRankAdshideLowReachhideNonEuUkAdshideSavedAdslandingPageslastSeenAfterlastSeenBeforelinkedDomainmainCountriesmarketmaxAdOrdermaxAdRankValuemaxAdReachGrowthmaxAdsmaxAdsPerBrandmaxAgemaxBestSellerPricemaxDatemaxDaysRunningmaxDescriptionLengthmaxDuplicatesmaxFacebookLikesmaxFbPageCreationDatemaxInstagramFollowersmaxLastSeenDatemaxMonthlyVisitsmaxPageAdsGrowthmaxPageAdsLaunchedmaxPageReachGrowthmaxProductsmaxProductsCountmaxReachmaxReachPerPagemaxSpendmaxSpendPerPagemaxTrafficmaxTrafficGrowthmaxVideoDurationmediaTypemediaTypesminAdOrderminAdReachGrowthminAdsminAgeminBestSellerPriceminDateminDaysRunningminDescriptionLengthminDuplicatesminFacebookLikesminFbPageCreationDateminInstagramFollowersminLastSeenDateminMonthlyVisitsminPageAdsGrowthminPageAdsLaunchedminPageReachGrowthminProductsminProductsCountminRankDeltaminReachminReachPerPageminSpendminSpendPerPageminTrafficminTrafficGrowthminVideoDurationpageAdsLaunchedPeriodpageReachGrowthpartnerIdspartnerspixelsplatformplatformsrankDeltaWindowreachPerPagePeriodreachPeriodsexshopCreatedAftershopCreatedBeforeshopifyAppsshopifyStoresOnlyspendPerPagePeriodspendPeriodstatustechnologiesthemestrackedPagestrafficGrowthwebsiteIds
curl -X POST "https://api.sellwinners.com/v1/media/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "mediaType": "video", "page": 1, "query": "skincare", "status": "active"}'

GET/v1/media/file/{key}

A media file (public, no key needed). Serves an image or video. These URLs appear in API responses and can be used directly in web pages. Add ?w=96 or ?w=480 for a smaller WebP copy of a JPEG, PNG, WebP or GIF image (never made larger, without the original's metadata); an animation, a smaller image or a video is sent as it is. Add ?w=full for the image at its own size as WebP, sent when it saves at least a tenth of the file (otherwise the original is sent).
ParameterDescription
keyrequired File key, as found in a media URL.
w 96 or 480: an image is sent at that width at most, as WebP, its aspect kept (96 for thumbnails, 480 for cards). full: at its own width and height, as WebP, when that is lighter (a record's own creative). Without it, the original file. One of: 96, 480, full.
curl "https://api.sellwinners.com/v1/media/file/FILE_KEY" \
  -H "X-API-Key: YOUR_API_KEY"

Advertisers

Advertisers (Facebook pages) and their activity.

GET/v1/advertisers

Search advertisers. searchType domain is the same as urlContains: URLs containing the text, so gymshark.com also finds pages linking to it. sex (men, women, unknown) is the audience of the page's ads; technologies takes a slug, a name or an id from /v1/facets/technologies. Growth ranges (adsGrowth, pageReachGrowth, trafficGrowth) are percentages over 30 days (adsGrowth also takes min14 and max14, over 14 days, and trafficGrowth min90 and max90, over 90 days; a rule's period may be last14d or last90d the same way). excludeAgeRanges leaves out age buckets of the page's ads (13-17 to 65+, as ageRanges takes them). shopCreatedAfter, shopCreatedBefore, creationCountries, excludeCreationCountries, marketCountries, mainMarketCountries, excludeMarketCountries, minProductsCount, maxProductsCount, and themeIds and shopifyAppIds (with their exclude names, ids from /v1/facets/*) filter the shop the page advertises. extra.domain is null when the page's website is not a shop (an app store, a social site, a link shortener). sortBy=reach ranks by the total reach since tracking began (extra.totalReach), newAds by the new ads of 14 days (extra.newAds14d) and followers by the Facebook likes and Instagram followers together; minReach and maxReach bound the total reach. Reach is EU and UK reach: advertising.reach30d, extra.reach14d, reach90d and totalReach are null for a page with no EU or UK ads and no reach (nullReasons eu_uk_only), or for a window the data source has not counted (not_measured); a page created inside a window has all its reach in it, and a row that reads no EU reach next to page details that read some has their reach, as its record does. The new-ads counts of a page created inside the window count every one of its ads, and where the data source has not computed the average live ads, those of a page created inside the window are the mean of its live ads read since its first day (extra.averagedFrom: the first day read), those of an older page null (extra.adsGrowth30d is null then). profile.instagramFollowers is null for a page with no Instagram account or none the data source knows. Shares are fractions: extra.euAdsShare is the share of the page's live ads shown in the EU or UK (0.0831 for 8.31%), extra.reachGrowth30d the growth of its EU reach over 30 days; extra.adCountries lists its live ads by target country ({countryCode, ads, share}) and extra.reachCountries its reach by country ({countryCode, impressions, share}), as its record has them. extra.newAds1d counts the ads it launched yesterday. mainLandingPages is empty on rows: the record has them (extra.mainLandingPages).
Named filters 59extra query parameters
adCountriesadLanguageadsGrowthadsLaunchedPeriodadsTimePeriodageRangescategoryIdscountriescountryFilterModecpmcreationCountriesexcludeAgeRangesexcludeCreationCountriesexcludeMarketCountriesexcludeShopifyAppIdsexcludeThemeIdsmainCountriesmainMarketCountriesmarketCountriesmaxActiveAdsmaxAdsGrowthmaxAdsLaunchedmaxAgemaxFacebookLikesmaxFbPageCreationDatemaxInstagramFollowersmaxPageReachGrowthmaxProductsCountmaxReachmaxReachPerPagemaxSpendPerPagemaxTrafficmaxTrafficGrowthminActiveAdsminAdsGrowthminAdsLaunchedminAgeminFacebookLikesminFbPageCreationDateminInstagramFollowersminPageReachGrowthminProductsCountminReachminReachPerPageminSpendPerPageminTrafficminTrafficGrowthpageNichespageReachGrowthpartnerssexshopCreatedAftershopCreatedBeforeshopifyAppIdsshopifyLinkedtechnologiesthemeIdstrackedPagestrafficGrowth
ParameterDescription
search Words to match: every field unless searchType narrows it (brand is the page name).
searchType What the search text is matched against: brand is the page name. Without it, the text is matched like all. One of: brand, adCopy, websiteCopy, urlContains, domain, all.
country 2-letter ISO country code.
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, activeAds, newAds, reach, reach14d, growth30d, followers, euAdsShare.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 20).
curl "https://api.sellwinners.com/v1/advertisers?search=nike&country=US&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/advertisers/query

Search advertisers with filters. searchType domain is the same as urlContains: URLs containing the text, so gymshark.com also finds pages linking to it. sex (men, women, unknown) is the audience of the page's ads; technologies takes a slug, a name or an id from /v1/facets/technologies. Growth ranges (adsGrowth, pageReachGrowth, trafficGrowth) are percentages over 30 days (adsGrowth also takes min14 and max14, over 14 days, and trafficGrowth min90 and max90, over 90 days; a rule's period may be last14d or last90d the same way). excludeAgeRanges leaves out age buckets of the page's ads (13-17 to 65+, as ageRanges takes them). shopCreatedAfter, shopCreatedBefore, creationCountries, excludeCreationCountries, marketCountries, mainMarketCountries, excludeMarketCountries, minProductsCount, maxProductsCount, and themeIds and shopifyAppIds (with their exclude names, ids from /v1/facets/*) filter the shop the page advertises. extra.domain is null when the page's website is not a shop (an app store, a social site, a link shortener). sortBy=reach ranks by the total reach since tracking began (extra.totalReach), newAds by the new ads of 14 days (extra.newAds14d) and followers by the Facebook likes and Instagram followers together; minReach and maxReach bound the total reach. Reach is EU and UK reach: advertising.reach30d, extra.reach14d, reach90d and totalReach are null for a page with no EU or UK ads and no reach (nullReasons eu_uk_only), or for a window the data source has not counted (not_measured); a page created inside a window has all its reach in it, and a row that reads no EU reach next to page details that read some has their reach, as its record does. The new-ads counts of a page created inside the window count every one of its ads, and where the data source has not computed the average live ads, those of a page created inside the window are the mean of its live ads read since its first day (extra.averagedFrom: the first day read), those of an older page null (extra.adsGrowth30d is null then). profile.instagramFollowers is null for a page with no Instagram account or none the data source knows. Shares are fractions: extra.euAdsShare is the share of the page's live ads shown in the EU or UK (0.0831 for 8.31%), extra.reachGrowth30d the growth of its EU reach over 30 days; extra.adCountries lists its live ads by target country ({countryCode, ads, share}) and extra.reachCountries its reach by country ({countryCode, impressions, share}), as its record has them. extra.newAds1d counts the ads it launched yesterday. mainLandingPages is empty on rows: the record has them (extra.mainLandingPages).
Named filters 59top-level body fields
adCountriesadLanguageadsGrowthadsLaunchedPeriodadsTimePeriodageRangescategoryIdscountriescountryFilterModecpmcreationCountriesexcludeAgeRangesexcludeCreationCountriesexcludeMarketCountriesexcludeShopifyAppIdsexcludeThemeIdsmainCountriesmainMarketCountriesmarketCountriesmaxActiveAdsmaxAdsGrowthmaxAdsLaunchedmaxAgemaxFacebookLikesmaxFbPageCreationDatemaxInstagramFollowersmaxPageReachGrowthmaxProductsCountmaxReachmaxReachPerPagemaxSpendPerPagemaxTrafficmaxTrafficGrowthminActiveAdsminAdsGrowthminAdsLaunchedminAgeminFacebookLikesminFbPageCreationDateminInstagramFollowersminPageReachGrowthminProductsCountminReachminReachPerPageminSpendPerPageminTrafficminTrafficGrowthpageNichespageReachGrowthpartnerssexshopCreatedAftershopCreatedBeforeshopifyAppIdsshopifyLinkedtechnologiesthemeIdstrackedPagestrafficGrowth
curl -X POST "https://api.sellwinners.com/v1/advertisers/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "minActiveAds": 10, "offset": 0, "query": "nike"}'

GET/v1/advertisers/{advertiserId}

One advertiser by id. Its reach is EU and UK reach, the advertiser search's own (the numbers advertiser lists show): advertising.reach30d, extra.reach14d and extra.totalReach (since tracking began); a page created inside a window has all its reach in it. A row's 0 next to page details that read EU reach is not a page with none: extra.totalReach is their reach so far. For a page with no EU or UK ads and no reach these and the estimates made from them are null, and nullReasons says why (eu_uk_only; not_measured for a window the data source has not counted). Its USD estimates are its reach at 9 USD per 1,000 people reached, with two decimals under 10 USD (1.26 for a reach of 140) and in whole dollars from 10 USD up. Its 14-day daily average, for a page created inside the 14 days, is its estimate so far over the whole days since it was created (one at least). extra.newAds7d, newAds14d and newAds30d count every ad of a page created inside the window. extra.avgActiveAds14d is the average of its live ads over 14 days: where the data source has not computed it, for a page created inside the 14 days the mean of its live ads read since its first day, from extra.averagedFrom.avgActiveAds14d (never before the day the page was created), else null (not_measured). advertising.countryDistribution is the page's live ads that target each country (ads) and their share of its live ads (an ad targets several, so the shares add up to more than 1), and extra.reachCountries the countries with reach, each with its share of it (one too small for 4 decimals unrounded, never 0); extra.reachScope says where most of that reach was seen: eu_uk, or outside_eu_uk for a page the data source reports the reach of from elsewhere too (its reach and the estimates made from it are then that reach, not EU reach). extra.history starts on the day the page was created and leaves out the readings the data source missed (a run of zeros of 14 days or fewer between two readings above 0; for the daily estimates, on days the page ran ads), and the new ads of 0 of the days it missed; extra.followersHistory leaves out a 0 between two readings above 0 or of such a day. The daily USD estimates of extra.history keep two decimals under 10 USD, read against the reach the page gained that day. extra.platforms.meta holds this page's own live (active) and total ads; extra.platforms.google and tiktok count the ads of the advertiser's website (all its pages), and extra.platforms.metaSite its Meta ads, each left out when the data source has no count. extra.bannerUrl, newAds1d (the new ads of yesterday), reach90d, newAds90d, avgActiveAds7d and avgActiveAds30d, linkedDomains, hasPartnershipAds and languages are those of the page's advertiser row, as advertiser lists show them. A page whose live ads are fewer than the live ads among its 24 newest ads (copies grouped) has a stale summary: advertising.activeAds and the new ads of yesterday, 7, 14, 30 and 90 days under what those ads show are raised to that floor, and extra.atLeast names the counters raised (none for a past day). For a page whose website is not a shop (an app store, a social or messaging site, a link shortener or a tracking redirect), extra.nonShopSite names that site and extra.platforms is left out (its counts are the site's), and linkedShops holds the shop most of its ads link to, from its landing pages (fromLandingPages true), or nothing. extra.mainLandingPages are the preview of its landing pages for a page the library has just seen. lastAds are its newest ads; for a page whose ads the ad search has not taken in yet, the latest ones its advertiser row lists (their id and media only), with meta.indexing true (also when it lists none yet); lastAds is empty, with meta.partial and a warning, when its newest ads could not be read. profile.instagramFollowers is null for a page with no Instagram account or none the data source knows. snapshotDate (a past day) gives the page's details as they were then (meta.snapshotDate).
ParameterDescription
advertiserIdrequired Facebook page id of an advertiser or ad.
snapshotDate A past day (YYYY-MM-DD): the page's details as they were then.
curl "https://api.sellwinners.com/v1/advertisers/ADVERTISER_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/advertisers/{advertiserId}/history

Daily live ads and EU reach of one advertiser. The page's live ads and the EU reach it gained, one reading a day, over the days asked (days: 7-3650, default 90; all: every reading the data source has), from the day the page was created. reach is empty when the data source reports none: nullReasons.reach is eu_uk_only for a page with no EU or UK ads (reach is reported for those only), not_measured for a page whose reach is not counted yet. The readings of 0 of a page with no EU ad now that gained reach before the days asked are kept (it gained none). Readings the data source missed are left out: a run of zeros of 14 days or fewer between two readings above 0 (for reach, on days the page ran ads).
ParameterDescription
advertiserIdrequired Facebook page id of an advertiser or ad.
days How many days back, 7-3650 (default 90), or all for every reading.
curl "https://api.sellwinners.com/v1/advertisers/ADVERTISER_ID/history?days=90" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/advertisers/{advertiser_id}/ads

Meta ads of one advertiser. All of its ads, the copies of one ad grouped in one row (metrics.duplicates counts them), so pagination.total counts the unique ads. sortBy=longestRunning takes order=desc only; sortBy=adRank lists the best rank (1) first, whatever the order. For a page whose ads the ad search has not taken in yet (a page the library has just seen), the first page is the latest ads its advertiser row lists (their id and media only), with meta.indexing true and meta.liveAds its live ads; with none listed yet the first page is empty, meta.indexing true all the same (meta.liveAds the live ads its page details count, for a page with no advertiser row yet).
ParameterDescription
advertiser_idrequired Facebook page id of an advertiser or ad.
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, reach, reachGrowth7d, reachDelta7d, longestRunning, duplicates, spend, adRank, rankDelta7d, rankDelta14d, rankDelta30d, createdAt, relevanceScore, mostDuplicates, adOrder.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 20).
curl "https://api.sellwinners.com/v1/advertisers/ADVERTISER_ID/ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

Emails

Brands' marketing and newsletter emails.

GET/v1/emails

Search brand emails. Without a campaign type (type, campaignTypes), Newsletter and Marketing emails are listed. Campaign types, categories, promotion types and events are the data source's names, in any case. Market countries (country, countries, amongMarketCountries) are any of the shop's: emails have no main market. shopIds takes shop ids or domains. A sentBefore date means before that day. A row's extra.shopMonthlyVisits and shopTrafficGrowth30d are left out for a site the traffic data has not measured yet (0 visits with a growth of 0 or none: nullReasons not_measured); extra.shopProductsCountCapped marks the data source's products ceiling (25,001: 25,000 or more); extra.shopAvgActiveAds7d, shopAvgActiveAds14d, shopAvgActiveAds30d, shopTotalAds, shopMarketCountries and shopMainMarket are the shop's figures. Growth ranges are percentages over 30 days (adsGrowth also takes min7 and max7, over 7 days). GET /v1/emails/facets/{facet} lists the values of the languages, countries, creationCountries, promotionTypes, eventNames, categories and campaignTypes filters with their emails.
Named filters 33extra query parameters
adsGrowthamongMarketCountriescampaignTypescategoriescategoryIdscountriescreationCountriesemailCategoryIdseventCategorieseventIdseventNamesexcludeLanguageslanguagesmaxActiveAdsmaxActiveAdsGrowthmaxBestSellerPricemaxMonthlyVisitsmaxProductsCountmaxTrafficGrowthminActiveAdsminActiveAdsGrowthminBestSellerPriceminMonthlyVisitsminProductsCountminTrafficGrowthpromotionTypeIdspromotionTypessentAftersentBeforeshopCreatedAftershopCreatedBeforeshopIdstrafficGrowth
ParameterDescription
search Words in the subject, sender or content.
type Campaign type, in any case (default: Newsletter and Marketing). One of: Marketing, Newsletter, Welcome, Abandoned Cart.
country 2-letter ISO code of a country the shop sells to (any of its market countries).
sortBy Defaults to relevance when searching, otherwise newest. One of: relevance, newest, event, promotionType, activeAds, emails90d, avgEmailsPerWeek, oldest, shopEmailFrequency.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/emails?search=black%20friday&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/emails/query

Search brand emails with filters. Without a campaign type (type, campaignTypes), Newsletter and Marketing emails are listed. Campaign types, categories, promotion types and events are the data source's names, in any case. Market countries (country, countries, amongMarketCountries) are any of the shop's: emails have no main market. shopIds takes shop ids or domains. A sentBefore date means before that day. A row's extra.shopMonthlyVisits and shopTrafficGrowth30d are left out for a site the traffic data has not measured yet (0 visits with a growth of 0 or none: nullReasons not_measured); extra.shopProductsCountCapped marks the data source's products ceiling (25,001: 25,000 or more); extra.shopAvgActiveAds7d, shopAvgActiveAds14d, shopAvgActiveAds30d, shopTotalAds, shopMarketCountries and shopMainMarket are the shop's figures. Growth ranges are percentages over 30 days (adsGrowth also takes min7 and max7, over 7 days). GET /v1/emails/facets/{facet} lists the values of the languages, countries, creationCountries, promotionTypes, eventNames, categories and campaignTypes filters with their emails.
Named filters 33top-level body fields
adsGrowthamongMarketCountriescampaignTypescategoriescategoryIdscountriescreationCountriesemailCategoryIdseventCategorieseventIdseventNamesexcludeLanguageslanguagesmaxActiveAdsmaxActiveAdsGrowthmaxBestSellerPricemaxMonthlyVisitsmaxProductsCountmaxTrafficGrowthminActiveAdsminActiveAdsGrowthminBestSellerPriceminMonthlyVisitsminProductsCountminTrafficGrowthpromotionTypeIdspromotionTypessentAftersentBeforeshopCreatedAftershopCreatedBeforeshopIdstrafficGrowth
curl -X POST "https://api.sellwinners.com/v1/emails/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"campaignTypes": ["Marketing"], "limit": 10, "page": 1, "query": "black friday", "sentAfter": "2025-11-01"}'

GET/v1/emails/{emailId}

One email by id. classification names the email's promotion type, category and event. The shop's monthly visits, live ads, products and 90-day figures are those the email lists show (shopEmails90d, shopAvgEmailsPerWeek), the same as the shop's email stats; marketing.activeAds is null for a 0 with no ad total (nullReasons not_measured), and marketing.avgActiveAds7d, avgActiveAds14d and avgActiveAds30d are the shop's average live ads the lists show. traffic.monthlyVisits and growth30d are null for a site the traffic data has not measured yet (0 visits with a growth of 0 or none: nullReasons not_measured). catalog.productsCountCapped marks the data source's products ceiling (25,001: 25,000 or more). shop.logoUrl is the shop's picture. extra.sender and content.preheader are those of the email's own row in the email lists (its details send neither): with no row for it, the sender is null with nullReasons not_reported. When the shop's figures could not be read they are null with nullReasons failed, meta.partial and a warning; so is the sender when the email's row could not be read.
ParameterDescription
emailIdrequired Email id from an email search.
curl "https://api.sellwinners.com/v1/emails/EMAIL_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/emails/{emailId}/html

Raw HTML of one email.
ParameterDescription
emailIdrequired Email id from an email search.
curl "https://api.sellwinners.com/v1/emails/EMAIL_ID/html" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shops/{shopId}/emails/stats

Email sending stats of a shop. The figures count the shop's emails of every campaign type (Marketing, Newsletter, Welcome and Abandoned Cart). last90Days.emailsByDayOfWeek is keyed by the day's number as the data source counts the days: 0 is Sunday, 1 Monday, up to 6, Saturday. last90Days.totalEmails and avgEmailsPerWeek are the figures the email lists show (shopEmails90d, shopAvgEmailsPerWeek), null when no email of the shop is tracked (nullReasons none_found) or the figures could not be read (meta.partial); calendar.partial marks a month cut at 500 emails.
ParameterDescription
shopIdrequired Shop id or domain, such as allbirds.com.
monthrequired Calendar month, as YYYY-MM.
curl "https://api.sellwinners.com/v1/shops/allbirds.com/emails/stats?month=2026-09" \
  -H "X-API-Key: YOUR_API_KEY"

Products

Store products with their price, sales, reviews, ads and EU reach.

GET/v1/products

Search or browse products. Each product has its price in the store's currency (`pricing.price`, `pricing.currency`) and in US dollars (`pricing.priceUsd`), `pricing.basePrice`, `discountPercent`, `onSale` and `isSubscription`; its sales estimates in whole US dollars (`sales.estDailySales`, and `sales.estMonthlySales`, 30 times the day) and its units sold a day (`sales.unitsSoldDaily`; `unitsSoldMonthly`, 30 times the day); its reviews (`reviews.rating`, null with no review, and `reviews.count`) and best-seller rank (`bestSeller.rank`, its place among its shop's products, 1 the best, and `rankPercent`, that place as a percent of the shop's products: 100 times the rank over `shop.productsCount`, so a low figure is a better rank); its Meta ads (`advertising.activeAds`, `totalAds`, `adsLaunched30d`, `adShare` and `spendShare` (percents, 0 to 100, as the minAdShare and minSpendShare filters take them, unlike the fractions of the other share fields), `advertisersCount`, and its latest ads, `advertising.latestAds`, each with its `id`, `platform`, `mediaType`, `mediaUrl` and `thumbnailUrl`, and their pictures, `advertising.previewUrls`), its EU reach (`eu.reach14d`, `reach30d`) and its EU spend in US dollars (`eu.spend30d`, `spendDaily`); its weeks (`weeks`, oldest first, up to 26: each with its `from` and `to` days, `activeAds`, `adShare` (a percent), and the EU spend a day in US dollars and reach a day, `euSpendDaily` and `euReachDaily`); the countries it sells to (`sellingCountries`), its launch date (`publishedAt`, UTC) and its shop (`shop.id`, `domain`, `name`, `logoUrl`, `estMonthlySales`, `monthlyVisits`, `productsCount`). `nullReasons` says why a figure is null: not_measured, or not_available for EU figures the index does not give on a product. `searchType` matches the text against the product's name (productName), its description (productDescription), its shop's domain (shop) or its address (url); without it, the index's own match. Named filters: minPriceUsd and maxPriceUsd (the price in USD); minEstMonthlySales and maxEstMonthlySales (the sales estimate of a month in USD, 30 times the day), or minEstDailySales and maxEstDailySales (a day's, sent as 30 days of it); minUnitsSoldMonthly and maxUnitsSoldMonthly (units sold in a month), or minUnitsSoldDaily and maxUnitsSoldDaily (a day's, sent as 30 days of it); sellingCountries (country codes: a product that sells to any of them); minActiveAds and maxActiveAds; minAdsLaunched and maxAdsLaunched (Meta ads launched in the last 30 days); minAdShare and maxAdShare, minSpendShare and maxSpendShare (percents); minEuReach and maxEuReach (the EU reach over 30 days); hasPartnershipAds (true or false); minReviews and maxReviews (the number of reviews), minRating and maxRating (the review score, 0 to 5); publishedAfter and publishedBefore (the launch day, YYYY-MM-DD); promoTypes (percent-off); currencies (the store's currency codes); subscription (subscription or one-time); shopCountries (the shop's country codes); minShopProductsCount and maxShopProductsCount (the shop's products). `shop` (one shop's domain or id) lists that shop's products only, with no search text. Also: excludeSellingCountries and mainSellingCountries (country codes); shopVisitorCountries (the countries its shop's visitors come from); minShopMonthlyVisits and maxShopMonthlyVisits; minShopTrafficGrowth30d and maxShopTrafficGrowth30d (a percent, which may be negative); adsLaunchedPeriod (the window of minAdsLaunched and maxAdsLaunched: 7d, 14d, 30d, the default, or all); minEuAdSpend and maxEuAdSpend (US dollars over 30 days); shopCreatedAfter and shopCreatedBefore (YYYY-MM-DD); shopifyAppIds, themeIds and pixelIds (ids from the filter lists). Other names of the same filters: minPrice, maxPrice, minMonthlyRevenue, maxMonthlyRevenue, minMonthlyUnitsSold, maxMonthlyUnitsSold, minReviewCount, maxReviewCount, partnership, shopId.
Named filters 60extra query parameters
adsLaunchedPeriodcurrenciesexcludeSellingCountrieshasPartnershipAdsmainSellingCountriesmaxActiveAdsmaxAdSharemaxAdsLaunchedmaxEstDailySalesmaxEstMonthlySalesmaxEuAdSpendmaxEuReachmaxMonthlyRevenuemaxMonthlyUnitsSoldmaxPricemaxPriceUsdmaxRatingmaxReviewCountmaxReviewsmaxShopMonthlyVisitsmaxShopProductsCountmaxShopTrafficGrowth30dmaxSpendSharemaxUnitsSoldDailymaxUnitsSoldMonthlyminActiveAdsminAdShareminAdsLaunchedminEstDailySalesminEstMonthlySalesminEuAdSpendminEuReachminMonthlyRevenueminMonthlyUnitsSoldminPriceminPriceUsdminRatingminReviewCountminReviewsminShopMonthlyVisitsminShopProductsCountminShopTrafficGrowth30dminSpendShareminUnitsSoldDailyminUnitsSoldMonthlypartnershippixelIdspromoTypespublishedAfterpublishedBeforesellingCountriesshopshopCountriesshopCreatedAftershopCreatedBeforeshopIdshopVisitorCountriesshopifyAppIdssubscriptionthemeIds
ParameterDescription
search Words to match: the product's name unless searchType says otherwise.
searchType What the text is matched against (shop: the shop's domain; url: the product's address). Without it, the index's own match. One of: productName, productDescription, shop, url.
sortBy Defaults to relevance. newest ranks by the launch date (createdAt is the same), activeAds by live Meta ads, spend by EU ad spend over the last 30 days, estSales by the sales estimate, adPressure by the ad share, and bestSelling by the best seller rank in its shop (rank 1 first whatever the order). One of: relevance, newest, activeAds, spend, estSales, bestSelling, adPressure, createdAt.
order Sort direction (default desc). One of: desc, asc.
page Page number, starting at 1.
offset Results to skip. Use it instead of page.
limit Results per page, 1-100 (default 24).
curl "https://api.sellwinners.com/v1/products?search=serum&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/products/query

Search products with filters. Body: query (or search), searchType, sortBy, order, page or offset, limit, and the named filters at the top level or inside filters, as on GET /v1/products. Each product has its price in the store's currency (`pricing.price`, `pricing.currency`) and in US dollars (`pricing.priceUsd`), `pricing.basePrice`, `discountPercent`, `onSale` and `isSubscription`; its sales estimates in whole US dollars (`sales.estDailySales`, and `sales.estMonthlySales`, 30 times the day) and its units sold a day (`sales.unitsSoldDaily`; `unitsSoldMonthly`, 30 times the day); its reviews (`reviews.rating`, null with no review, and `reviews.count`) and best-seller rank (`bestSeller.rank`, its place among its shop's products, 1 the best, and `rankPercent`, that place as a percent of the shop's products: 100 times the rank over `shop.productsCount`, so a low figure is a better rank); its Meta ads (`advertising.activeAds`, `totalAds`, `adsLaunched30d`, `adShare` and `spendShare` (percents, 0 to 100, as the minAdShare and minSpendShare filters take them, unlike the fractions of the other share fields), `advertisersCount`, and its latest ads, `advertising.latestAds`, each with its `id`, `platform`, `mediaType`, `mediaUrl` and `thumbnailUrl`, and their pictures, `advertising.previewUrls`), its EU reach (`eu.reach14d`, `reach30d`) and its EU spend in US dollars (`eu.spend30d`, `spendDaily`); its weeks (`weeks`, oldest first, up to 26: each with its `from` and `to` days, `activeAds`, `adShare` (a percent), and the EU spend a day in US dollars and reach a day, `euSpendDaily` and `euReachDaily`); the countries it sells to (`sellingCountries`), its launch date (`publishedAt`, UTC) and its shop (`shop.id`, `domain`, `name`, `logoUrl`, `estMonthlySales`, `monthlyVisits`, `productsCount`). `nullReasons` says why a figure is null: not_measured, or not_available for EU figures the index does not give on a product. `searchType` matches the text against the product's name (productName), its description (productDescription), its shop's domain (shop) or its address (url); without it, the index's own match. Named filters: minPriceUsd and maxPriceUsd (the price in USD); minEstMonthlySales and maxEstMonthlySales (the sales estimate of a month in USD, 30 times the day), or minEstDailySales and maxEstDailySales (a day's, sent as 30 days of it); minUnitsSoldMonthly and maxUnitsSoldMonthly (units sold in a month), or minUnitsSoldDaily and maxUnitsSoldDaily (a day's, sent as 30 days of it); sellingCountries (country codes: a product that sells to any of them); minActiveAds and maxActiveAds; minAdsLaunched and maxAdsLaunched (Meta ads launched in the last 30 days); minAdShare and maxAdShare, minSpendShare and maxSpendShare (percents); minEuReach and maxEuReach (the EU reach over 30 days); hasPartnershipAds (true or false); minReviews and maxReviews (the number of reviews), minRating and maxRating (the review score, 0 to 5); publishedAfter and publishedBefore (the launch day, YYYY-MM-DD); promoTypes (percent-off); currencies (the store's currency codes); subscription (subscription or one-time); shopCountries (the shop's country codes); minShopProductsCount and maxShopProductsCount (the shop's products). `shop` (one shop's domain or id) lists that shop's products only, with no search text. Also: excludeSellingCountries and mainSellingCountries (country codes); shopVisitorCountries (the countries its shop's visitors come from); minShopMonthlyVisits and maxShopMonthlyVisits; minShopTrafficGrowth30d and maxShopTrafficGrowth30d (a percent, which may be negative); adsLaunchedPeriod (the window of minAdsLaunched and maxAdsLaunched: 7d, 14d, 30d, the default, or all); minEuAdSpend and maxEuAdSpend (US dollars over 30 days); shopCreatedAfter and shopCreatedBefore (YYYY-MM-DD); shopifyAppIds, themeIds and pixelIds (ids from the filter lists). Other names of the same filters: minPrice, maxPrice, minMonthlyRevenue, maxMonthlyRevenue, minMonthlyUnitsSold, maxMonthlyUnitsSold, minReviewCount, maxReviewCount, partnership, shopId.
Named filters 60top-level body fields
adsLaunchedPeriodcurrenciesexcludeSellingCountrieshasPartnershipAdsmainSellingCountriesmaxActiveAdsmaxAdSharemaxAdsLaunchedmaxEstDailySalesmaxEstMonthlySalesmaxEuAdSpendmaxEuReachmaxMonthlyRevenuemaxMonthlyUnitsSoldmaxPricemaxPriceUsdmaxRatingmaxReviewCountmaxReviewsmaxShopMonthlyVisitsmaxShopProductsCountmaxShopTrafficGrowth30dmaxSpendSharemaxUnitsSoldDailymaxUnitsSoldMonthlyminActiveAdsminAdShareminAdsLaunchedminEstDailySalesminEstMonthlySalesminEuAdSpendminEuReachminMonthlyRevenueminMonthlyUnitsSoldminPriceminPriceUsdminRatingminReviewCountminReviewsminShopMonthlyVisitsminShopProductsCountminShopTrafficGrowth30dminSpendShareminUnitsSoldDailyminUnitsSoldMonthlypartnershippixelIdspromoTypespublishedAfterpublishedBeforesellingCountriesshopshopCountriesshopCreatedAftershopCreatedBeforeshopIdshopVisitorCountriesshopifyAppIdssubscriptionthemeIds
curl -X POST "https://api.sellwinners.com/v1/products/query" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"limit": 10, "minActiveAds": 10, "minPriceUsd": 20, "offset": 0, "query": "serum", "sortBy": "activeAds"}'

GET/v1/products/{productId}

Get a product. One product as a search returns it, with `detail`: its photos, options and variants from the store's own page. `productId` is a row's `ref`.
ParameterDescription
productIdrequired The product's `ref`, as a product search returns it.
curl "https://api.sellwinners.com/v1/products/SHOP_ID:PRODUCT_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/products/lookup

Look up a product by its page address. The product behind a Shopify product page (`url`), as GET /v1/products/{productId} answers it.
ParameterDescription
urlrequired A Shopify product page's address, https://<shop>/products/<handle>.
curl "https://api.sellwinners.com/v1/products/lookup?url=https%3A//example.com/products/blue-mug" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/products/{productId}/ads

List a product's ads. The Meta ads that link to the product's page, newest first, in the format of /v1/ads. `status`: active or inactive.
ParameterDescription
productIdrequired The product's `ref`, as a product search returns it.
status active or inactive. One of: active, inactive.
page Page number, starting at 1.
limit Results per page (1-100, default 10).
curl "https://api.sellwinners.com/v1/products/SHOP_ID:PRODUCT_ID/ads" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/products/{productId}/share-links

Create (or return) a public link to a product. Anyone with the link can view the product's sheet on the website without an account, with no EU data.
ParameterDescription
productIdrequired The product's `ref`, as a product search returns it.
curl -X POST "https://api.sellwinners.com/v1/products/SHOP_ID:PRODUCT_ID/share-links" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/products/{productId}/share-links

Remove the public link to a product.
ParameterDescription
productIdrequired The product's `ref`, as a product search returns it.
curl -X DELETE "https://api.sellwinners.com/v1/products/SHOP_ID:PRODUCT_ID/share-links" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shared/products/{token}

A product behind a share link (no key needed). The same record the share page shows, as JSON.
ParameterDescription
tokenrequired Token at the end of a share link.
curl "https://api.sellwinners.com/v1/shared/products/TOKEN" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/products/facets

Filter values for product search. The same list as GET /v1/filters/products. Free of credits.
curl "https://api.sellwinners.com/v1/products/facets" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/products/image-search/history

Your recent image searches. Your own image searches, newest first: searchId (to read it again), kind (upload or url), label (the file's name or the URL's host and file), total (the matches it found), createdAt and queryImage (a small copy of the picture, a data URI). Only the searches of your account are listed.
ParameterDescription
limit How many, newest first (1-20, default 10).
curl "https://api.sellwinners.com/v1/products/image-search/history?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/products/image-search/{searchId}

Read an image search again. Another page, sort, filter or results per shop of one of your image searches, without sending the picture again; a search of another account, or one that has expired, answers 404 not_found. Store products that look like the picture, each with its shop, the closest first: a product row as the product search answers it (GET /v1/products), with `similarity` (0.7 to 1, how close it is to the picture) and `matchOnly` (true for a match the product index has no record of: its title, picture, price, launch date and shop only, its figures null). `maxPerShop` keeps the closest 1, 3, 5, 10 or 20 matches of each shop (0, the default: all). Pages of 32 at most (`limit`), by `page` or `offset`. `meta.searchId` is the search's id: GET /v1/products/image-search/{searchId} reads its other pages, sorts, filters and results per shop without sending the picture again (the same matches: `meta.total` does not change with the sort). `meta.queryImage` is a small copy of the picture (a data URI), `meta.depthCapped` marks a list that ends before its total (narrow it with filters), `meta.similarityThreshold` the lowest similarity answered. The picture is written again before it is searched (as a JPEG without its metadata) and a URL is downloaded by us, never passed on. Errors: 400 invalid_image (not a PNG, JPG or WEBP file, or over 10 MB), 400 unsupported_url (not an http or https URL, or a private or local address), 422 unreadable_image (a file that does not decode, or a URL that does not download), 504 upstream_timeout. Each search is counted as one request, a replay too; answers are never cached. On Free, image search is ranked by relevance with no filters, as the plan's policy says.
ParameterDescription
searchIdrequired The searchId an image search answered (meta.searchId).
filters A JSON object of the product search's named filters.
sortBy Defaults to relevance. One of: relevance, estSales, activeAds, adPressure, newest, spend, spend14d.
order Sort direction (default desc). One of: desc, asc.
maxPerShop 0 (all), 1, 3, 5, 10 or 20.
page Page number, starting at 1.
offset Number of results to skip.
limit Results per page (1-32).
curl "https://api.sellwinners.com/v1/products/image-search/SEARCH_ID?sortBy=activeAds&page=2" \
  -H "X-API-Key: YOUR_API_KEY"

Facets

The values and ids the search filters take.

GET/v1/facets/categories

Categories (ids for the categoryIds filters). The ids taken by every categoryIds filter. Each row has id, name, path, parentId and usageCount.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/facets/categories?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/facets/shopify-apps

Shopify apps (ids for the app filters).
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/facets/shopify-apps?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/facets/technologies

Storefront technologies (slugs for the technologies filter).
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/facets/technologies?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/facets/pixels

Tracking pixels (ids for the pixel filters).
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/facets/pixels?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/facets/themes

Shopify themes (ids for the theme filters).
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/facets/themes?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/facets/email-classifications

Email categories, promotion types and events. The ids taken by emailCategoryIds, promotionTypeIds and eventIds, and the event categories taken by eventCategories, in email searches.
curl "https://api.sellwinners.com/v1/facets/email-classifications" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/google-ads/facets/networks

Google ad networks.
curl "https://api.sellwinners.com/v1/google-ads/facets/networks" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/google-ads/facets/countries

Google ad audience countries.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/google-ads/facets/countries?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/google-ads/facets/formats

Google ad formats. The values the formats filter of a Google search takes (text, image, video), each with the ads it counts (adsCount), most first. On paid plans, as Google ads are.
curl "https://api.sellwinners.com/v1/google-ads/facets/formats" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/google-ads/facets/statuses

Google ad statuses. The values the status filter of a Google search takes (active, inactive), each with the ads the data source counts for it (adsCount): an ad it still marks active that Google has not shown for more than 7 days counts as active here, though status=active leaves it out. On paid plans, as Google ads are.
curl "https://api.sellwinners.com/v1/google-ads/facets/statuses" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/google-ads/facets/categories

Categories of Google advertisers. Each row has id, name, path, parentId and advertiserUsageCount.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/google-ads/facets/categories?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tiktok/facets/categories

TikTok categories. The names the categories filter of a TikTok search takes, as the data source spells them. Each row has value, label and postsCount (the posts the category counts), most first. On paid plans, as TikTok is.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/tiktok/facets/categories?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tiktok/facets/languages

TikTok languages. The names the languages filter of a TikTok search takes (english). Each row has value, label and postsCount (the posts it counts), most first. On paid plans, as TikTok is.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/tiktok/facets/languages?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tiktok/facets/countries

TikTok countries. The two-letter codes the countries filter of a TikTok search takes. Each row has value, label and postsCount (the posts it counts), most first. On paid plans, as TikTok is.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/tiktok/facets/countries?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tiktok/facets/content-types

TikTok content types. The content types of TikTok posts (ad, organic: the type filter). Each row has value, label and postsCount (the posts it counts), most first. On paid plans, as TikTok is.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/tiktok/facets/content-types?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/tiktok/facets/media-types

TikTok media types. The media types of TikTok posts (video, carousel: the mediaType filter). Each row has value, label and postsCount (the posts it counts), most first. On paid plans, as TikTok is.
ParameterDescription
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/tiktok/facets/media-types?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/emails/facets/{facet}

Email filter values. The values an email filter takes, each with the emails it counts (emails), most first: languages (the names the languages filters take), countries (the shop's market countries), creationCountries (the country the shop was created in), promotionTypes, eventNames, categories and campaignTypes (the data source's names). On paid plans, as emails are.
ParameterDescription
facetrequired The list: languages, countries, creationCountries, promotionTypes, eventNames, categories or campaignTypes.
search Only options whose name contains this text.
limit Options per page, 1-500 (default 100).
offset Options to skip.
curl "https://api.sellwinners.com/v1/emails/facets/promotionTypes?limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/filters/shops

Filter values for shop search. The values the shop search's raw filters take (countryCodes, visitorCountryCodes, activeAdsRanges, productRanges, shopifyApps, shopifyThemes), each {value, label, count}, read once an hour; meta.shopsTracked is the number of shops the data source tracks. On paid plans.
curl "https://api.sellwinners.com/v1/filters/shops" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/filters/advertisers

Filter values for advertiser search. The values the advertiser search's audience filters take: ageRanges, sexes, languages and countryCodes, each {value, label, count} (the pages counted), most first. On paid plans, as advertisers are.
curl "https://api.sellwinners.com/v1/filters/advertisers" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/filters/products

Filter values for product search. The values the product search's currencies filter takes, each with the count the index gives it.
curl "https://api.sellwinners.com/v1/filters/products" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/filters/ads

Filter values for ad search.
curl "https://api.sellwinners.com/v1/filters/ads" \
  -H "X-API-Key: YOUR_API_KEY"

Boards

Save ads, shops, products, emails and advertisers on boards, and share them.

GET/v1/boards

List boards.
ParameterDescription
scope Defaults to workspace. One of: workspace, personal.
state Defaults to active. One of: active, archived.
kind A collection holds items, a folder holds boards. One of: collection, folder.
surface What the board is for. One of: ads, shops, landing, emails, products, advertisers, mixed.
parentBoardId Only boards inside this folder board.
rootOnly Only top-level boards. One of: true, false.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/boards?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/boards

Create a board. Body: name, and optionally kind (collection or folder), surface (ads, shops, landing, emails, products, advertisers, mixed), description, visibility (private, workspace, public) and parentBoardId.
curl -X POST "https://api.sellwinners.com/v1/boards" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"kind": "collection", "name": "Skincare winners", "surface": "ads", "visibility": "workspace"}'

GET/v1/boards/{boardId}

Get a board.
ParameterDescription
boardIdrequired Board id.
curl "https://api.sellwinners.com/v1/boards/BOARD_ID" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/boards/{boardId}

Update a board. Send at least one of name, description or visibility.
ParameterDescription
boardIdrequired Board id.
curl -X PATCH "https://api.sellwinners.com/v1/boards/BOARD_ID" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"description": "Ads worth a second look.", "name": "Skincare winners 2026"}'

DELETE/v1/boards/{boardId}

Archive a board. Archives the board and everything under it. The restore endpoint brings it back.
ParameterDescription
boardIdrequired Board id.
curl -X DELETE "https://api.sellwinners.com/v1/boards/BOARD_ID" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/boards/{boardId}/restore

Restore an archived board.
ParameterDescription
boardIdrequired Board id.
curl -X POST "https://api.sellwinners.com/v1/boards/BOARD_ID/restore" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/boards/{boardId}/parent

Move a board. parentBoardId is a folder board; null moves the board to the top level.
ParameterDescription
boardIdrequired Board id.
curl -X PATCH "https://api.sellwinners.com/v1/boards/BOARD_ID/parent" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"parentBoardId": "BOARD_ID"}'

GET/v1/boards/{boardId}/items

List the items of a board.
ParameterDescription
boardIdrequired Board id.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
include item adds the saved copy of each record. One of: item.
curl "https://api.sellwinners.com/v1/boards/BOARD_ID/items?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/boards/{boardId}/items

Add an item to a board. sourceType is meta_ad, google_ad, tiktok, shop, email, advertiser or product (a product is saved as a search last showed it). Adding an item twice returns the existing one with created: false.
ParameterDescription
boardIdrequired Board id.
curl -X POST "https://api.sellwinners.com/v1/boards/BOARD_ID/items" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"sourceId": "AD_ID", "sourceType": "meta_ad"}'

POST/v1/boards/{boardId}/items/{itemId}/move

Move an item to another board.
ParameterDescription
boardIdrequired Board id.
itemIdrequired Item id.
curl -X POST "https://api.sellwinners.com/v1/boards/BOARD_ID/items/ITEM_ID/move" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"targetBoardId": "BOARD_ID"}'

DELETE/v1/boards/{boardId}/items/{itemId}

Remove an item from a board.
ParameterDescription
boardIdrequired Board id.
itemIdrequired Item id.
curl -X DELETE "https://api.sellwinners.com/v1/boards/BOARD_ID/items/ITEM_ID" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/boards/{boardId}/share-links

Create a public link to a board. The answer carries a url: a web page anyone can open, without an API key. Each call creates a new link.
ParameterDescription
boardIdrequired Board id.
curl -X POST "https://api.sellwinners.com/v1/boards/BOARD_ID/share-links" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/boards/{boardId}/share-links

Remove the public links to a board. Every link to the board stops working at once; the board itself stays.
ParameterDescription
boardIdrequired Board id.
curl -X DELETE "https://api.sellwinners.com/v1/boards/BOARD_ID/share-links" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/shared/boards/{token}

A board behind a share link (no key needed). The same board the share page shows, as JSON.
ParameterDescription
tokenrequired Token at the end of a share link.
curl "https://api.sellwinners.com/v1/shared/boards/TOKEN" \
  -H "X-API-Key: YOUR_API_KEY"

Favorites

Favorite ads, shops and emails, in folders.

GET/v1/favorites/ads

List favorite ads.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
folderId Only favorites in this folder.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/favorites/ads?scope=workspace&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/favorites/ads

Save a favorite ad. Body: scope, adId and optionally folderId and sourceType (meta_ad by default; google_ad or tiktok saves a Google ad or a TikTok post by its id). Each saved ad names its adId and sourceType. Saving the same ad twice returns the saved one with created: false.
curl -X POST "https://api.sellwinners.com/v1/favorites/ads" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"adId": "AD_ID", "scope": "workspace"}'

PATCH/v1/favorites/ads/saved/{favoriteId}/folder

Move a saved favorite ad.
ParameterDescription
favoriteIdrequired id of a saved favorite, from the favorites list.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/ads/saved/FAVORITE_ID/folder?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"folderId": "FOLDER_ID"}'

DELETE/v1/favorites/ads/saved/{favoriteId}

Delete a saved favorite ad.
ParameterDescription
favoriteIdrequired id of a saved favorite, from the favorites list.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/ads/saved/FAVORITE_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/favorites/ads/{recordId}

Remove a favorite ad by its adId.
ParameterDescription
recordIdrequired The adId of the saved ad.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
folderId Only remove it from this folder.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/ads/RECORD_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/favorites/ads/folders

List favorite ad folders.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
parentId Only folders inside this folder.
rootOnly Only top-level folders. One of: true, false.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/favorites/ads/folders?scope=workspace&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/favorites/ads/folders

Create a favorite ad folder. Body: scope, name and optionally parentId.
curl -X POST "https://api.sellwinners.com/v1/favorites/ads/folders" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Winners", "scope": "workspace"}'

PATCH/v1/favorites/ads/folders/reorder

Check a favorite ad folder order. Folders have no stored order: the list is checked and echoed back sorted by order. The answer carries reordered: true.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/ads/folders/reorder?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"folders": [{"id": "FOLDER_ID", "order": 0}]}'

POST/v1/favorites/ads/folders/{folderId}/share

Create a public link to a favorite ad folder.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X POST "https://api.sellwinners.com/v1/favorites/ads/folders/FOLDER_ID/share?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/favorites/ads/folders/{folderId}/share

Remove the public links to a favorite ad folder.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/ads/folders/FOLDER_ID/share?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/favorites/ads/folders/{folderId}/visibility

Set favorite ad folder visibility. visibility is private or organization.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/ads/folders/FOLDER_ID/visibility?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"visibility": "private"}'

PATCH/v1/favorites/ads/folders/{folderId}

Rename or move a favorite ad folder. Body: name, and parentId to move the folder (null moves it to the top level).
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/ads/folders/FOLDER_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Top performers"}'

DELETE/v1/favorites/ads/folders/{folderId}

Delete a favorite ad folder. mode is delete_items, move_items_to_root or move_items_to_folder (with targetFolderId).
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/ads/folders/FOLDER_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"mode": "move_items_to_root"}'

GET/v1/favorites/shops

List favorite shops.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
folderId Only favorites in this folder.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/favorites/shops?scope=workspace&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/favorites/shops

Save a favorite shop. Body: scope, websiteId and optionally folderId. Saving the same shop twice returns the saved one with created: false.
curl -X POST "https://api.sellwinners.com/v1/favorites/shops" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"scope": "workspace", "websiteId": "SHOP_ID"}'

PATCH/v1/favorites/shops/saved/{favoriteId}/folder

Move a saved favorite shop.
ParameterDescription
favoriteIdrequired id of a saved favorite, from the favorites list.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/shops/saved/FAVORITE_ID/folder?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"folderId": "FOLDER_ID"}'

DELETE/v1/favorites/shops/saved/{favoriteId}

Delete a saved favorite shop.
ParameterDescription
favoriteIdrequired id of a saved favorite, from the favorites list.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/shops/saved/FAVORITE_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/favorites/shops/{recordId}

Remove a favorite shop by its websiteId.
ParameterDescription
recordIdrequired The websiteId of the saved shop.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
folderId Only remove it from this folder.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/shops/RECORD_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/favorites/shops/folders

List favorite shop folders.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/favorites/shops/folders?scope=workspace&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/favorites/shops/folders

Create a favorite shop folder. Body: scope, name.
curl -X POST "https://api.sellwinners.com/v1/favorites/shops/folders" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Winners", "scope": "workspace"}'

PATCH/v1/favorites/shops/folders/reorder

Check a favorite shop folder order. Folders have no stored order: the list is checked and echoed back sorted by order. The answer carries reordered: true.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/shops/folders/reorder?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"folders": [{"id": "FOLDER_ID", "order": 0}]}'

POST/v1/favorites/shops/folders/{folderId}/share

Create a public link to a favorite shop folder.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X POST "https://api.sellwinners.com/v1/favorites/shops/folders/FOLDER_ID/share?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/favorites/shops/folders/{folderId}/share

Remove the public links to a favorite shop folder.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/shops/folders/FOLDER_ID/share?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/favorites/shops/folders/{folderId}/visibility

Set favorite shop folder visibility. visibility is private or organization.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/shops/folders/FOLDER_ID/visibility?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"visibility": "private"}'

PATCH/v1/favorites/shops/folders/{folderId}

Rename or move a favorite shop folder. Body: name.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/shops/folders/FOLDER_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Top performers"}'

DELETE/v1/favorites/shops/folders/{folderId}

Delete a favorite shop folder. mode is delete_items, move_items_to_root or move_items_to_folder (with targetFolderId).
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/shops/folders/FOLDER_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"mode": "move_items_to_root"}'

GET/v1/favorites/emails

List favorite emails.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
folderId Only favorites in this folder.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/favorites/emails?scope=workspace&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/favorites/emails

Save a favorite email. Body: scope, emailId and optionally folderId. Saving the same email twice returns the saved one with created: false.
curl -X POST "https://api.sellwinners.com/v1/favorites/emails" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"emailId": 123456, "scope": "workspace"}'

PATCH/v1/favorites/emails/saved/{favoriteId}/folder

Move a saved favorite email.
ParameterDescription
favoriteIdrequired id of a saved favorite, from the favorites list.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/emails/saved/FAVORITE_ID/folder?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"folderId": "FOLDER_ID"}'

DELETE/v1/favorites/emails/saved/{favoriteId}

Delete a saved favorite email.
ParameterDescription
favoriteIdrequired id of a saved favorite, from the favorites list.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/emails/saved/FAVORITE_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/favorites/emails/{recordId}

Remove a favorite email by its emailId.
ParameterDescription
recordIdrequired The emailId of the saved email.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
folderId Only remove it from this folder.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/emails/RECORD_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/favorites/emails/folders

List favorite email folders.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
parentId Only folders inside this folder.
rootOnly Only top-level folders. One of: true, false.
page Page number, starting at 1.
limit Results per page, 1-100 (default 25).
curl "https://api.sellwinners.com/v1/favorites/emails/folders?scope=workspace&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/favorites/emails/folders

Create a favorite email folder. Body: scope, name and optionally parentId.
curl -X POST "https://api.sellwinners.com/v1/favorites/emails/folders" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Winners", "scope": "workspace"}'

PATCH/v1/favorites/emails/folders/reorder

Check a favorite email folder order. Folders have no stored order: the list is checked and echoed back sorted by order. The answer carries reordered: true.
ParameterDescription
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/emails/folders/reorder?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"folders": [{"id": "FOLDER_ID", "order": 0}]}'

POST/v1/favorites/emails/folders/{folderId}/share

Create a public link to a favorite email folder.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X POST "https://api.sellwinners.com/v1/favorites/emails/folders/FOLDER_ID/share?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/favorites/emails/folders/{folderId}/share

Remove the public links to a favorite email folder.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/emails/folders/FOLDER_ID/share?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/favorites/emails/folders/{folderId}/visibility

Set favorite email folder visibility. visibility is private or organization.
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/emails/folders/FOLDER_ID/visibility?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"visibility": "private"}'

PATCH/v1/favorites/emails/folders/{folderId}

Rename or move a favorite email folder. Body: name, and parentId to move the folder (null moves it to the top level).
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X PATCH "https://api.sellwinners.com/v1/favorites/emails/folders/FOLDER_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Top performers"}'

DELETE/v1/favorites/emails/folders/{folderId}

Delete a favorite email folder. mode is delete_items, move_items_to_root or move_items_to_folder (with targetFolderId).
ParameterDescription
folderIdrequired Folder id.
scoperequired Which favorites: shared with the workspace or personal. One of: workspace, personal.
curl -X DELETE "https://api.sellwinners.com/v1/favorites/emails/folders/FOLDER_ID?scope=workspace" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"mode": "move_items_to_root"}'

Saved views

The searches you saved on the website's list pages, by page.

GET/v1/views

List your saved views. Each view has its name, its state (the page's query string, as the website writes it), request (the search it makes: search, searchType, sortBy, order and the named filters, as the search endpoints take them) and ui (the page's own choices: a date preset such as last30 is worked out from today on the page, while the filters hold the days it had when the view was saved), in the order you gave them. On the Free plan, listed where the plan includes reading or saving saved items. Our own data: the data source is never asked.
ParameterDescription
context Only this list page's views. Defaults to every page. One of: shops, meta, tiktok, google, advertisers, emails, products.
curl "https://api.sellwinners.com/v1/views" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/views

Save a view. Body: context (shops, meta, tiktok, google, advertisers, emails, products), name (1 to 60 characters, one per name on a page) and state (the page's query string: search, searchType, sortBy, order, view, the named filters as f.<name> or f.<name>.<key>, and the page's choices as v.<id>; 16,000 characters at most). Every filter is checked as the page's search checks it. 50 views per page. On the Free plan, open where it includes saving to boards and favorites, and on a page whose search it has in full (Meta ads).
curl -X POST "https://api.sellwinners.com/v1/views" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"context": "shops", "name": "Big US shops", "state": "f.marketCountries=US\u0026f.minMonthlyVisits=100000\u0026sortBy=monthlyVisits"}'

PATCH/v1/views/{viewId}

Rename, move or change a saved view. Send at least one of name, position (its place among the page's views, 0 the first) or state.
ParameterDescription
viewIdrequired id of a saved view, from the list of your views.
curl -X PATCH "https://api.sellwinners.com/v1/views/VIEW_ID" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Big US shops 2026", "position": 0}'

DELETE/v1/views/{viewId}

Delete a saved view. Open on every plan; the page's other views keep their order.
ParameterDescription
viewIdrequired id of a saved view, from the list of your views.
curl -X DELETE "https://api.sellwinners.com/v1/views/VIEW_ID" \
  -H "X-API-Key: YOUR_API_KEY"

Brand trackers

Follow brands and read reports on their ads, creatives and landing pages.

GET/v1/brandtrackers

List tracked brands. A counter the source could not give is null, with nullReasons (failed, not_measured; totalTraffic: not_measured, also for a site not measured yet, which reads 0, or no_shop for a page with no shop) and, when a read failed, meta.partial. Sorting puts unknown values last. totalTraffic is read again once a day. advertising.activeAds here is the page's daily count; one tracked brand with a shop reads its shop's newest count (the one its charts end on), so the two can differ. A 0 of advertising.newAdsLastDay beside launches in the last 7 days is checked against the shop's launches of yesterday: their count, or null (not_measured) when there is no reading of that day. At most 20 brands are checked a call, those of the page asked for (sorted by newAdsLastDay or with hasNewAdsSince of yesterday, the first 20 in tracked order, newest first); the others are null (not_measured).
ParameterDescription
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
name Only brands whose name or domain contains this text, or with this page id.
hasNewAdsSince Only brands with new ads since this date, such as 2026-09-30.
sortBy One of: newAdsLastDay, newAdsLast7Days, newAdsLast30Days, activeAds, totalTraffic, name, createdAt.
folderIds Only these folders, comma-separated; none: the brands in no folder.
folderNames Only folders with these names, comma-separated.
curl "https://api.sellwinners.com/v1/brandtrackers?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/brandtrackers

Track a brand. Body: exactly one of facebookPageId, websiteId, shopId or domain, and optionally folderId. Tracking a brand twice returns the existing tracker with created: false (a shop tracked before through another of its pages too). A shop is followed through its own Facebook page running the most ads (its main page on a tie; never a partner's Whitelisting page).
curl -X POST "https://api.sellwinners.com/v1/brandtrackers" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"domain": "allbirds.com"}'

GET/v1/brandtrackers/{brandtrackerId}

One tracked brand. statistics.euData.reach30d and estimatedSpend30d cover the last 30 days (reach and estimatedSpend are the lifetime totals; a spend keeps two decimals under 10 USD and is in whole dollars from 10 USD up); a count the source does not send is null and nullReasons says why (eu_uk_only, not_measured, failed, no_shop). liveAdCount.activeCount and advertising.activeAds are one count, the one the brand's charts end on; pageProfile.runningAds is the page details' own count. advertising.newAdsLastDay is checked as on the list. statistics.urlCounts lists the landing pages of statistics.urlCount with their live ads ({url, ads, activeAds}); statistics.changes30d holds the changes over 30 days of its live ads, the ads it launched and its EU reach, each with its change as a fraction (activeAdsChange30d, activeAdsChange30dPct, launchedChange30d, launchedChange30dPct, reachChange30d, reachChange30dPct); statistics.firstAdSeenAt, longestRunningDays and medianRunningDays say how long its ads run, and statistics.targetCountries lists the countries its live ads target ({countryCode, ads, share}); these are null (or empty) for a brand with no shop.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/brandtrackers/{brandtrackerId}

Stop tracking a brand.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
curl -X DELETE "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/overview

Dashboard view of a brand. Graph, media mix, top landing pages, top ads and the newest ads of a brand in one answer. A part that could not be read is null, with meta.partial and meta.warnings; meta.dataFreshnessLagDays is the age in days of the newest ad, given when the brand launched ads after it (0 otherwise: a brand that stopped launching is not a lag).
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/overview" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/snapshots

Snapshot dates of a brand. The days recorded for a brand, newest first. Built from a daily record that starts the day the brand is tracked.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-365 (default 100).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/snapshots?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/ads

Ads of a brand. Newest first by default; then, with no filter (status and EU ads only included), meta.latestAdDate is the start of the brand's newest ad in the library and meta.dataFreshnessLagDays its age in days when the brand launched ads after it (the library can be a day or two behind the live counters), 0 otherwise. The first page of the ads of one ad text (adCopyHashes) has both too, since a text's count in ad-copies is of today's live ads; with status active, meta.stoppedCount is the number of its stopped ads.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to newest. One of: newest, longestRunning, reach, duplicates, relevance, reachDelta7d, currentRank, rankDelta7d, rankDelta14d, rankDelta30d, spend.
status Running or stopped ads. One of: active, inactive, all.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
keywords Words in the ad copy.
createdAfter Launched on or after this date, such as 2026-09-01.
createdBefore Launched on or before this date.
minDaysRunning Running for at least this many days.
maxDaysRunning Running for at most this many days.
minDuplicates At least this many copies of the ad.
maxDuplicates At most this many copies of the ad.
adLanguage Language of the ad.
cta Call to action.
adCopyHashes Ad text ids from the ad-copies report, comma-separated.
adCountries Countries the ads run in, comma-separated.
mainCountries Main country of the ads, comma-separated.
partners true: only partnership ads. One of: true, false.
partnerIds Only ads with these partner pages (Facebook page ids), comma-separated.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/timeline

A brand's ads in launch order.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to newest. One of: newest, longestRunning, reach, duplicates, relevance, reachDelta7d, currentRank, rankDelta7d, rankDelta14d, rankDelta30d, spend.
status Running or stopped ads. One of: active, inactive, all.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
keywords Words in the ad copy.
createdAfter Launched on or after this date, such as 2026-09-01.
createdBefore Launched on or before this date.
minDaysRunning Running for at least this many days.
maxDaysRunning Running for at most this many days.
minDuplicates At least this many copies of the ad.
maxDuplicates At most this many copies of the ad.
adLanguage Language of the ad.
cta Call to action.
adCopyHashes Ad text ids from the ad-copies report, comma-separated.
adCountries Countries the ads run in, comma-separated.
mainCountries Main country of the ads, comma-separated.
partners true: only partnership ads. One of: true, false.
partnerIds Only ads with these partner pages (Facebook page ids), comma-separated.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/timeline?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/timeline/metadata

Count and date range of a brand's timeline. totalIsExact is false when totalCount is a lower bound; totalCount is null when the source sends no total.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
status Running or stopped ads. One of: active, inactive, all.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
keywords Words in the ad copy.
createdAfter Launched on or after this date, such as 2026-09-01.
createdBefore Launched on or before this date.
minDaysRunning Running for at least this many days.
maxDaysRunning Running for at most this many days.
minDuplicates At least this many copies of the ad.
maxDuplicates At most this many copies of the ad.
adLanguage Language of the ad.
cta Call to action.
adCopyHashes Ad text ids from the ad-copies report, comma-separated.
adCountries Countries the ads run in, comma-separated.
mainCountries Main country of the ads, comma-separated.
partners true: only partnership ads. One of: true, false.
partnerIds Only ads with these partner pages (Facebook page ids), comma-separated.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/timeline/metadata" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/partnership-ads

Partnership ads of a brand.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to newest. One of: newest, longestRunning, reach, duplicates, relevance, reachDelta7d, currentRank, rankDelta7d, rankDelta14d, rankDelta30d, spend.
status Running or stopped ads. One of: active, inactive, all.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
keywords Words in the ad copy.
createdAfter Launched on or after this date, such as 2026-09-01.
createdBefore Launched on or before this date.
minDaysRunning Running for at least this many days.
maxDaysRunning Running for at most this many days.
minDuplicates At least this many copies of the ad.
maxDuplicates At most this many copies of the ad.
adLanguage Language of the ad.
cta Call to action.
adCopyHashes Ad text ids from the ad-copies report, comma-separated.
adCountries Countries the ads run in, comma-separated.
mainCountries Main country of the ads, comma-separated.
partners true: only partnership ads. One of: true, false.
partnerIds Only ads with these partner pages (Facebook page ids), comma-separated.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/partnership-ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/partnership-ads/count

Number of partnership ads of a brand. isExact is false when count is a lower bound; count is null when the source sends no total.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
status Running or stopped ads. One of: active, inactive, all.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
keywords Words in the ad copy.
createdAfter Launched on or after this date, such as 2026-09-01.
createdBefore Launched on or before this date.
minDaysRunning Running for at least this many days.
maxDaysRunning Running for at most this many days.
minDuplicates At least this many copies of the ad.
maxDuplicates At most this many copies of the ad.
adLanguage Language of the ad.
cta Call to action.
adCopyHashes Ad text ids from the ad-copies report, comma-separated.
adCountries Countries the ads run in, comma-separated.
mainCountries Main country of the ads, comma-separated.
partners true: only partnership ads. One of: true, false.
partnerIds Only ads with these partner pages (Facebook page ids), comma-separated.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/partnership-ads/count" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/top-ads

A brand's ads, ranked. metrics.totalReach is the ad's EU reach: null for an ad shown outside the EU and the UK (nullReasons metrics.totalReach eu_uk_only) or an EU ad not counted yet (not_measured), and last in a reach sort.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to currentRank. One of: currentRank, rankDelta, rankDelta7d, rankDelta14d, rankDelta30d, reach, reachDelta7d, daysRunning, duplicates.
status Defaults to active. One of: active, inactive, all.
includeInactive Also rank stopped ads. One of: true, false.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/top-ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/ad-rank

A brand's ads that gained rank. Ads that gained rank over a window, with their rank history. Each row's ranks come from that history: metrics.currentRank is its reading of the day the ad library's rank was read (the rank Top ads shows; the library can be a day behind the history), else its newest reading, the trajectory ends on that day, metrics.previousRank is the reading of the day the window starts, metrics.rankDelta the previous rank minus the current one (positive: places gained) and metrics.improvementPct the fraction of the previous rank gained (0.875 is 87.5%). With no reading that day (an ad's rank history can start after a 14 or 30-day window does), previousRank is the rank of the oldest reading inside the window and metrics.since its day, and meta.windowNote says so; a figure that cannot be given is null with nullReasons not_measured. The ad library's first 50 ads (by its own count of rank gained, or by rank) are ranked again by these figures: an ad that gained less than minRankDelta, or ranks below maxCurrentRank, by them is left out (an ad whose rank history gives no gain, by the ad library's own count), pagination covers the ads kept, and meta.rankNote says what was read and left out (across brands too, for every brand read).
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
timeWindow Defaults to last7d. One of: last7d, last14d, last30d.
sortBy Defaults to rankDelta. One of: rankDelta, currentRank.
maxCurrentRank Only ads ranked at or above this position.
minRankDelta Positions gained, at least (default 1).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/ad-rank?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/scaling-ads

A brand's scaling ads. Same answer as /ad-rank.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
timeWindow Defaults to last7d. One of: last7d, last14d, last30d.
sortBy Defaults to rankDelta. One of: rankDelta, currentRank.
maxCurrentRank Only ads ranked at or above this position.
minRankDelta Positions gained, at least (default 1).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/scaling-ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/creatives

Creatives of a brand. mediaType is image, video, carousel (an ad of several images or videos, as in its ad record) or unknown.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
timePeriod Which ads to read (default live). One of: live, last24h, last3d, last7d, last30d, last3m, last6m, last1y.
mediaType Creative type. One of: all, image, video.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to firstSeenAt. One of: firstSeenAt, daysRunning, duplicates.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/creatives?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/testing

Creative tests of a brand. Ads grouped by the day they were launched, from the 400 newest ads. A batch is a winner when one of its ads is still running a week or more after launch. Its reach and days stats cover the ads whose value is known (null when none is, and then bestPerformerId is null too, with nullReasons stats.reach: eu_uk_only when every ad of the batch was shown outside the EU and the UK, not_measured when one of its ads is not counted yet, else no_eu_reach: none of its ads has an EU or UK reach reported); partial is true on the oldest batch when the 400-ad read stopped inside it.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
status Running or stopped ads. One of: active, inactive, all.
mediaType Creative type. One of: image, video, dco, carousel, dpa.
keywords Words in the ad copy.
createdAfter Launched on or after this date, such as 2026-09-01.
createdBefore Launched on or before this date.
minDaysRunning Running for at least this many days.
maxDaysRunning Running for at most this many days.
minDuplicates At least this many copies of the ad.
maxDuplicates At most this many copies of the ad.
adLanguage Language of the ad.
cta Call to action.
adCopyHashes Ad text ids from the ad-copies report, comma-separated.
adCountries Countries the ads run in, comma-separated.
mainCountries Main country of the ads, comma-separated.
partners true: only partnership ads. One of: true, false.
partnerIds Only ads with these partner pages (Facebook page ids), comma-separated.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/testing?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/hooks

Hooks a brand opens its videos with. totalImpressions is the EU and UK reach of the ads using it (people reached, not impressions: the old name, kept), and euReach the same figure under its name: both null when none of them has any counted (nullReasons no_eu_reach; not_measured with euOnly or when it is not sent), and last in its sort. firstUsedAt and lastUsedAt are the launch days of the first and the newest ad using it (a text still live has its newest launch there, not a day it stopped). pagination.total is the data source's count of the texts; a brand with more than 1,000 lists its first 1,000 (read 200 at a time), with meta.partial and a warning.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
timePeriod Which ads to read (default live). One of: live, last24h, last3d, last7d, last30d, last3m, last6m, last1y.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to usageCount. One of: usageCount, longestRunning, totalImpressions, firstUsedAt, lastUsedAt.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/hooks?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/transcripts

Video scripts of a brand. totalImpressions is the EU and UK reach of the ads using it (people reached, not impressions: the old name, kept), and euReach the same figure under its name: both null when none of them has any counted (nullReasons no_eu_reach; not_measured with euOnly or when it is not sent), and last in its sort. firstUsedAt and lastUsedAt are the launch days of the first and the newest ad using it (a text still live has its newest launch there, not a day it stopped). pagination.total is the data source's count of the texts; a brand with more than 1,000 lists its first 1,000 (read 200 at a time), with meta.partial and a warning. Each transcript has its hook: the opening line the data source reads in it (null without one).
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
timePeriod Which ads to read (default live). One of: live, last24h, last3d, last7d, last30d, last3m, last6m, last1y.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to usageCount. One of: usageCount, longestRunning, totalImpressions, firstUsedAt, lastUsedAt.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/transcripts?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/headlines

Headlines of a brand's ads. totalImpressions is the EU and UK reach of the ads using it (people reached, not impressions: the old name, kept), and euReach the same figure under its name: both null when none of them has any counted (nullReasons no_eu_reach; not_measured with euOnly or when it is not sent), and last in its sort. firstUsedAt and lastUsedAt are the launch days of the first and the newest ad using it (a text still live has its newest launch there, not a day it stopped). pagination.total is the data source's count of the texts; a brand with more than 1,000 lists its first 1,000 (read 200 at a time), with meta.partial and a warning. Headlines carry what hooks do: firstUsedAt, lastUsedAt, sampleAd and the reach of their ads.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
timePeriod Which ads to read (default live). One of: live, last24h, last3d, last7d, last30d, last3m, last6m, last1y.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to usageCount. One of: usageCount, longestRunning, totalImpressions, firstUsedAt, lastUsedAt.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/headlines?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/ad-copies

Ad texts of a brand. Ad texts and how many live ads use each; longestRunning is null when the age of its ads is unknown.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/ad-copies?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/landing-pages

Landing pages of a brand. Every Facebook page of the brand's shop counts. totalImpressions is the EU and UK reach of the ads using it (people reached, not impressions: the old name, kept), and euReach the same figure under its name: both null when none of them has any counted (nullReasons no_eu_reach; not_measured with euOnly or when it is not sent), and last in its sort. Each page has its live ads (activeAds), its first live day (activeSince), its status, shareOfAds (the share of the brand's live ads linking to it, a fraction), reachByCountry ({countryCode, reach}) and targetedCountries. On a past day (snapshotDate) the pages as they were then, the day in meta.snapshotDate.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to usageCount. One of: usageCount, longestRunning, totalImpressions.
order Sort direction (default desc). One of: desc, asc.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/landing-pages?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/landing-pages/simple

Landing pages of a brand, grouped by page. Query strings, fragments, trailing slashes and a leading www. are ignored when grouping.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to usageCount. One of: usageCount, activeAdsCount.
order Sort direction (default desc). One of: desc, asc.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/landing-pages/simple?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/ad-copy-evolution

Ad texts of a brand over time. Ads using each ad text, day by day. Built from a daily record that starts the day the brand is tracked. A series has a point for every recorded day of the range: 0 on a day the text was not used, null on a day that kept only its most used texts. A day whose live ads read under a tenth of the days on both sides of it (2 or 3 such days in a row too; the newest day stays as read), or that recorded far fewer texts than the days on both sides of it (or none, beside live ads), is left out (meta.periodNote says so); meta.recordedDays counts the days.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-25 (default 10).
startDate First day, such as 2026-09-01.
endDate Last day.
adCopy Only this ad text.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/ad-copy-evolution?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/headline-evolution

Headlines of a brand over time. Ads using each headline, day by day. Built from a daily record that starts the day the brand is tracked. A series has a point for every recorded day of the range: 0 on a day the text was not used, null on a day that kept only its most used texts. A day whose live ads read under a tenth of the days on both sides of it (2 or 3 such days in a row too; the newest day stays as read), or that recorded far fewer texts than the days on both sides of it (or none, beside live ads), is left out (meta.periodNote says so); meta.recordedDays counts the days.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-25 (default 10).
startDate First day, such as 2026-09-01.
endDate Last day.
headline Only this headline.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/headline-evolution?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/landing-page-evolution

Landing pages of a brand over time. Each page's readings by day. The days the data source read the brand's live ads wrong (under a tenth of the days on both sides of them) are left out of every page, and so is a page's own reading under a tenth of its readings on both sides; meta.periodNote counts them and, when the history is behind (meta.dataFreshnessLagDays), says up to which day it reaches.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-25 (default 10).
startDate First day, such as 2026-09-01.
endDate Last day.
landingPage Only this landing page URL.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/landing-page-evolution?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/partners

Partners running ads for a brand. Each partner page once. isOwnPage is true for a page of the brand's own shop (its main page, or an official page named like the brand: creators who run its partnership ads can be ranked official too) and for a page named as the brand. reach and estimatedSpend are null when the source has not measured them, with nullReasons not_measured in the 7 days after the partner's launchDate and no_eu_reach after (no EU or UK reach counted for its ads).
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
page Page number, starting at 1.
limit Results per page, 1-50 (default 20).
sortBy Defaults to activeAds. One of: activeAds, launchDate, reach, estimatedSpend.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
cpm Cost per 1,000 impressions used for the spend estimate (default 9).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/partners?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/media-mix

Format mix of a brand's live ads.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/media-mix" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/demography

Audience of a brand's ads. Audience in the EU and the UK: the people reached, by country, by age range and by gender (each breakdown has its own base). A count the source does not send is null; hasData is true when one count is above 0. A country whose count is under a ten-thousandth of the top country's is left out of countryDistribution and listed in otherCountries. On a past day (snapshotDate) the audience as it was then, the day in meta.snapshotDate.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/demography" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/activity

A tracked brand's newest items of one source. Each item in its source's search-row shape (Meta ads, TikTok posts, Google ads, emails), newest first, over 90 days at most. meta.partial is true when the data source read the window only in part, and meta.partialSources names the source then. The feed covers a few sample brands only: another tracked brand answers 404.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
source Defaults to meta. One of: meta, tiktok, google, email.
since First day (YYYY-MM-DD; default 6 days before until: 7 days).
until Last day, included (YYYY-MM-DD; default today).
page Page number, starting at 1.
limit Results per page, 1-100 (default 24).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/activity?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/activity/events

A tracked brand's events. Each event: type, date, occurredAt, itemId (the ad, post or email), title, imageUrl, url and details. meta.partial is true when the data source read the window only in part, and meta.partialSources names the sources the types asked for name (meta for new_meta_ads). The feed covers a few sample brands only: another tracked brand answers 404.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
since First day (YYYY-MM-DD; default 6 days before until: 7 days).
until Last day, included (YYYY-MM-DD; default today).
types Event types, comma-separated (default new_meta_ads).
page Page number, starting at 1.
limit Results per page, 1-100 (default 24).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/activity/events?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/activity/calendar

A tracked brand's calendar across Meta, TikTok, Google and email. The items of each source (meta, tiktok, google, email) over 31 days at most, a preview each; with day, that day's items in their search-row shape; both read on while the data source has more, 10 calls at most (meta.isTruncated when more were left); times in UTC. meta.partial is true when the data source read some sources only in part, and meta.partialSources names them. The feed covers a few sample brands only: another tracked brand answers 404.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
since First day (YYYY-MM-DD; default 6 days before until: 7 days).
until Last day, included (YYYY-MM-DD; default today).
day One day (YYYY-MM-DD): its items in full.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/activity/calendar" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/activity/calendar/days

How much a tracked brand launched each day, by source. days: the count of each day and source (meta, tiktok, google, email), over 31 days at most; previews: a preview of each item, its times in UTC. meta.partial is true when the data source read the window only in part. The feed covers a few sample brands only: another tracked brand answers 404.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
since First day (YYYY-MM-DD; default 6 days before until: 7 days).
until Last day, included (YYYY-MM-DD; default today).
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/activity/calendar/days" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/{brandtrackerId}/time-series

Ads launched, live ads and reach over time. Weekly and monthly points carry startDate, endDate and partial (a bucket the range holds only part of); a period starts on the first day of its first week or month. Live ads of a bucket are the median of its daily readings, leaving out a reading (or 2 or 3 in a row) under a tenth of the readings around it. Such a day, with days on both sides of it, is null in a daily series (a drop on the newest day stays as read: a brand can stop its ads), its launches too, and so are the launches of the day after it when they are nearly all its live ads (the ads read again); weeks and months leave those launches out, and leftOut lists the days (days, launchDays), also in the overview's graph. A value the source does not send is null; impressions is the EU and UK reach of the brand's ads (people reached; the old name, kept) and euReach the same figure; when the range has no EU reach at all, impressions, euReach and estimatedSpend are null and nullReasons.euImpressionsSpend says why (eu_uk_only, not_measured). estimatedSpend keeps two decimals under 10 USD (1.26) and is in whole dollars from 10 USD up.
ParameterDescription
brandtrackerIdrequired Tracker id, from the list of tracked brands.
granularity Defaults to daily. One of: daily, weekly, monthly.
period Use it instead of startDate / endDate. One of: today, yesterday, 1d, 7d, 14d, 30d, 90d, 365d.
startDate First day, such as 2026-09-01.
endDate Last day.
euOnly Only ads shown in the EU and UK. One of: true, false.
cpm Cost per 1,000 impressions used for the spend estimate.
curl "https://api.sellwinners.com/v1/brandtrackers/BRANDTRACKER_ID/time-series" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/top-ads

Top ads across tracked brands. Runs over your 100 most recent tracked brands (top-ads and scaling-ads also over those with no shop). Narrow it with brandtrackerIds or folderIds. meta.perBrandCap is the rows a brand gives at most; a brand whose report fails or that your plan leaves out is in meta.skippedBrands (reason failed, plan or unavailable), with meta.partial; when every brand fails the call fails. The shop reports (hooks, ad-copies, landing-pages, media-mix) count the brands with no shop in meta.brandsWithoutShop.
ParameterDescription
brandtrackerIds Only these trackers, comma-separated.
folderIds Only trackers in these folders, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to currentRank. One of: currentRank, rankDelta, rankDelta7d, reach, reachDelta7d, daysRunning, duplicates.
includeInactive Also rank stopped ads. One of: true, false.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/workspace/top-ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/scaling-ads

Scaling ads across tracked brands. Runs over your 100 most recent tracked brands (top-ads and scaling-ads also over those with no shop). Narrow it with brandtrackerIds or folderIds. meta.perBrandCap is the rows a brand gives at most; a brand whose report fails or that your plan leaves out is in meta.skippedBrands (reason failed, plan or unavailable), with meta.partial; when every brand fails the call fails. The shop reports (hooks, ad-copies, landing-pages, media-mix) count the brands with no shop in meta.brandsWithoutShop.
ParameterDescription
brandtrackerIds Only these trackers, comma-separated.
folderIds Only trackers in these folders, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to rankDelta. One of: rankDelta, currentRank.
period Window of the rank change (default last7d). Where an ad's rank history starts inside it, metrics.since is the day previousRank and rankDelta count from, and meta.windowNote says so. Each brand's ranks come from its ads' rank histories, as in its own /ad-rank: its first 10 ads in the ad library's ranking, ranked again, those that gained less than asked left out, as meta.rankNote says for all the brands read. One of: last7d, last14d, last30d.
maxCurrentRank Only ads ranked at or above this position.
minRankDelta Positions gained, at least (default 1).
curl "https://api.sellwinners.com/v1/workspace/scaling-ads?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/hooks

Hooks across tracked brands. Runs over your 100 most recent tracked brands (top-ads and scaling-ads also over those with no shop). Narrow it with brandtrackerIds or folderIds. meta.perBrandCap is the rows a brand gives at most; a brand whose report fails or that your plan leaves out is in meta.skippedBrands (reason failed, plan or unavailable), with meta.partial; when every brand fails the call fails. The shop reports (hooks, ad-copies, landing-pages, media-mix) count the brands with no shop in meta.brandsWithoutShop.
ParameterDescription
brandtrackerIds Only these trackers, comma-separated.
folderIds Only trackers in these folders, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to usageCount. One of: usageCount, longestRunning, totalImpressions, firstUsedAt, lastUsedAt.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/workspace/hooks?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/ad-copies

Ad texts across tracked brands. Runs over your 100 most recent tracked brands (top-ads and scaling-ads also over those with no shop). Narrow it with brandtrackerIds or folderIds. meta.perBrandCap is the rows a brand gives at most; a brand whose report fails or that your plan leaves out is in meta.skippedBrands (reason failed, plan or unavailable), with meta.partial; when every brand fails the call fails. The shop reports (hooks, ad-copies, landing-pages, media-mix) count the brands with no shop in meta.brandsWithoutShop.
ParameterDescription
brandtrackerIds Only these trackers, comma-separated.
folderIds Only trackers in these folders, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to usageCount. One of: usageCount.
order Sort direction (default desc). One of: desc, asc.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/workspace/ad-copies?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/landing-pages

Landing pages across tracked brands. Runs over your 100 most recent tracked brands (top-ads and scaling-ads also over those with no shop). Narrow it with brandtrackerIds or folderIds. meta.perBrandCap is the rows a brand gives at most; a brand whose report fails or that your plan leaves out is in meta.skippedBrands (reason failed, plan or unavailable), with meta.partial; when every brand fails the call fails. The shop reports (hooks, ad-copies, landing-pages, media-mix) count the brands with no shop in meta.brandsWithoutShop.
ParameterDescription
brandtrackerIds Only these trackers, comma-separated.
folderIds Only trackers in these folders, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to usageCount. One of: usageCount, longestRunning, totalImpressions.
order Sort direction (default desc). One of: desc, asc.
curl "https://api.sellwinners.com/v1/workspace/landing-pages?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/media-mix

Format mix across tracked brands. Runs over your 100 most recent tracked brands (top-ads and scaling-ads also over those with no shop). Narrow it with brandtrackerIds or folderIds. meta.perBrandCap is the rows a brand gives at most; a brand whose report fails or that your plan leaves out is in meta.skippedBrands (reason failed, plan or unavailable), with meta.partial; when every brand fails the call fails. The shop reports (hooks, ad-copies, landing-pages, media-mix) count the brands with no shop in meta.brandsWithoutShop.
ParameterDescription
brandtrackerIds Only these trackers, comma-separated.
folderIds Only trackers in these folders, comma-separated.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
sortBy Defaults to activeAds. One of: activeAds, image, video, dco, other.
euOnly Only ads shown in the EU and UK. One of: true, false.
curl "https://api.sellwinners.com/v1/workspace/media-mix?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/brandtrackers/folders

List tracker folders.
curl "https://api.sellwinners.com/v1/brandtrackers/folders" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace/folders

List tracker folders. Same answer as /v1/brandtrackers/folders.
curl "https://api.sellwinners.com/v1/workspace/folders" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/brandtrackers/folders

Create a tracker folder.
curl -X POST "https://api.sellwinners.com/v1/brandtrackers/folders" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Competitors"}'

PATCH/v1/brandtrackers/folders/{folderId}

Rename a tracker folder.
ParameterDescription
folderIdrequired Folder id.
curl -X PATCH "https://api.sellwinners.com/v1/brandtrackers/folders/FOLDER_ID" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Direct competitors"}'

DELETE/v1/brandtrackers/folders/{folderId}

Delete a tracker folder. action is move-to-default (keeps the trackers) or delete-brandtrackers (removes them).
ParameterDescription
folderIdrequired Folder id.
curl -X DELETE "https://api.sellwinners.com/v1/brandtrackers/folders/FOLDER_ID" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"action": "move-to-default", "confirm": true}'

GET/v1/brandtrackers/folders/{folderId}/brandtrackers

Trackers in a folder.
ParameterDescription
folderIdrequired Folder id.
page Page number, starting at 1.
limit Results per page, 1-100 (default 20).
name Only brands whose name or domain contains this text, or with this page id.
hasNewAdsSince Only brands with new ads since this date, such as 2026-09-30.
sortBy One of: newAdsLastDay, newAdsLast7Days, newAdsLast30Days, activeAds, totalTraffic, name, createdAt.
curl "https://api.sellwinners.com/v1/brandtrackers/folders/FOLDER_ID/brandtrackers?limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

Account

Your key, plan and usage. These calls are never counted.

GET/v1/account

Your plan, credits and usage this month.
curl "https://api.sellwinners.com/v1/account" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/usage

Credits used and left this month.
curl "https://api.sellwinners.com/v1/usage" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/me

The API key in use and its workspace.
curl "https://api.sellwinners.com/v1/me" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace

The workspace behind the API key.
curl "https://api.sellwinners.com/v1/workspace" \
  -H "X-API-Key: YOUR_API_KEY"

Workspaces

Your workspaces, their members and seats, and the invitations sent and received. These calls are never counted.

GET/v1/workspaces

List your workspaces. Each with its id, name, slug, your role (owner, admin, member or readonly), its plan, its seats (limit, used, remaining, activeMembers, activeInvitations, included, extra: a pending invitation holds a seat) and isDefault (opened on sign-in). Your own workspace comes first.
curl "https://api.sellwinners.com/v1/workspaces" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/workspaces

Create a workspace. Body: name (1 to 60 characters). It starts on the Free plan with you as its owner; you can own 10.
curl -X POST "https://api.sellwinners.com/v1/workspaces" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Growth team"}'

PUT/v1/workspaces/default

Choose your default workspace. The website opens it when you sign in.
curl -X PUT "https://api.sellwinners.com/v1/workspaces/default" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"workspaceId": "ws_1000000001"}'

GET/v1/workspaces/{workspaceId}

One of your workspaces. A workspace you don't belong to answers 404.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
curl "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/workspaces/{workspaceId}

Rename a workspace. Owners and admins only.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
curl -X PATCH "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Growth team"}'

DELETE/v1/workspaces/{workspaceId}

Remove a workspace. The owner only. Refused while other members remain (409 workspace_has_members), while its subscription renews (409 subscription_renews) and for your last workspace (409 last_workspace).
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
curl -X DELETE "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspaces/{workspaceId}/members

List a workspace's members. Every member with their email and role, the owner first, and the seats. Every member can read it.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
curl "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/members" \
  -H "X-API-Key: YOUR_API_KEY"

PATCH/v1/workspaces/{workspaceId}/members/{userId}

Change a member's role. The owner changes anyone but themself; an admin changes members and readonly members only. The owner role can't be changed.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
userIdrequired A member's user id (user_...), from the workspace's members.
curl -X PATCH "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/members/USER_ID" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"role": "readonly"}'

DELETE/v1/workspaces/{workspaceId}/members/{userId}

Remove a member. They lose access at once; getting them back takes a new invitation.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
userIdrequired A member's user id (user_...), from the workspace's members.
curl -X DELETE "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/members/USER_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspaces/{workspaceId}/invitations

List pending invitations. Owners and admins only, newest first, each with its email, role, who sent it and when it expires.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
curl "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/invitations" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/workspaces/{workspaceId}/invitations

Invite someone. role: member (the default), readonly, or admin (the owner only). It takes a seat until accepted, declined, revoked or expired (7 days). Refused: 409 already_member, invitation_exists or seat_limit_reached. emailSent false: send it again with resend.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
curl -X POST "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/invitations" \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "role": "member"}'

POST/v1/workspaces/{workspaceId}/invitations/{invitationId}/resend

Send an invitation again. A new link (the old one stops working), valid 7 days. At most once a minute.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
invitationIdrequired id of an invitation (inv_...).
curl -X POST "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/invitations/INVITATION_ID/resend" \
  -H "X-API-Key: YOUR_API_KEY"

DELETE/v1/workspaces/{workspaceId}/invitations/{invitationId}

Revoke an invitation. It stops working at once and its seat is free again.
ParameterDescription
workspaceIdrequired id of one of your workspaces (ws_...), from the list of your workspaces.
invitationIdrequired id of an invitation (inv_...).
curl -X DELETE "https://api.sellwinners.com/v1/workspaces/WORKSPACE_ID/invitations/INVITATION_ID" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace-invitations/pending

Invitations you received. The open invitations sent to your account's email, with the workspace, the role and the expiry.
curl "https://api.sellwinners.com/v1/workspace-invitations/pending" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/workspace-invitations/{invitationId}

One invitation you received. Its status: active, accepted, declined, revoked or expired.
ParameterDescription
invitationIdrequired id of an invitation (inv_...).
curl "https://api.sellwinners.com/v1/workspace-invitations/INVITATION_ID" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/workspace-invitations/{invitationId}/accept

Accept an invitation. Join with the role offered. 410 invitation_closed when it is no longer open (details.status says why).
ParameterDescription
invitationIdrequired id of an invitation (inv_...).
curl -X POST "https://api.sellwinners.com/v1/workspace-invitations/INVITATION_ID/accept" \
  -H "X-API-Key: YOUR_API_KEY"

POST/v1/workspace-invitations/{invitationId}/decline

Decline an invitation. The seat it held is free again.
ParameterDescription
invitationIdrequired id of an invitation (inv_...).
curl -X POST "https://api.sellwinners.com/v1/workspace-invitations/INVITATION_ID/decline" \
  -H "X-API-Key: YOUR_API_KEY"

System

Service status. No API key needed.

GET/v1

API root.
curl "https://api.sellwinners.com/v1" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/health

Service status (no key needed).
curl "https://api.sellwinners.com/v1/health" \
  -H "X-API-Key: YOUR_API_KEY"

GET/v1/system/freshness

How fresh the data is (no key needed).
curl "https://api.sellwinners.com/v1/system/freshness" \
  -H "X-API-Key: YOUR_API_KEY"

MCP server

Our hosted MCP server exposes the same data as tools for AI agents. Use the same API key as the REST API; a tool call costs the results it returns, like the API, and its answer says so in meta.credits (used, remaining, source). It also exposes three resources: sellwinners://me, sellwinners://usage and sellwinners://openapi.

The Free plan includes the MCP server too: 150 credits a month, 10 requests a minute, the first 10 results of each search. On Free, the tool list names the tools Free includes; another tool answers a tool error ending with [plan_not_eligible], which isn't counted. On a paid plan, a tool call the plan doesn't include returns a tool error ending with [plan_not_eligible], which isn't counted.

URL        https://mcp.sellwinners.com/mcp
Transport  streamable HTTP
Header     X-API-Key: YOUR_API_KEY

The list tools (search_shops, find_similar_shops, search_products, search_ads, search_google_ads_library, search_tiktok_library, search_advertisers, search_emails) answer compact rows by default, small enough for an assistant to read inline: each row keeps its ids, names and domains, its key figures and dates, its links, one picture, text cut to 200 characters and the last points of its histories, under the same field names as the full row, with the answer's pagination as it is. Pass detail="full" for every field of each row, or open one record with scan_ad, scan_advertiser, brief_competitor or shop_report.

Client setup

No API key: these sign in with your SellWinners account.
The Free plan includes the MCP server too: 150 credits a month, 10
requests a minute, the first 10 results of each search.

1. In ChatGPT (an app or a connector in developer mode) or in
   Claude (Customize → Connectors → Add custom connector; on Team or
   Enterprise an Owner adds it and you select Connect),
   add this server URL:  https://mcp.sellwinners.com/mcp
2. Choose OAuth if asked. A SellWinners window opens:
   log in, then select Allow.
3. Ask: "Find the top video ads for running shoes this month".

Disconnect any time: Settings → MCP → Connected apps.

Tools

Discovery 3
lookupResolve a brand name, a shop domain or a Facebook page id to ids you can use with the other tools
3 arguments
qtexttypetextlimitnumber
lookup_filter_idsIds for the filters of the search tools
7 arguments
typetextquerytextscope_tracked_pageslistscope_domaintextstatustextlimitnumbersnapshot_datetext
list_saved_viewsThe searches you saved on the website's list pages, ready for the search tools
1 argument
contexttext
Shops 17
search_shopsSearch or browse Shopify stores
48 arguments
querytextmatch_modetextcountrytextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtextcreation_countrytextcreation_countrieslistexclude_creation_countrieslistcreation_date_fromtextcreation_date_totextmin_active_adsnumbermax_active_adsnumbermin_monthly_visitsnumbermax_monthly_visitsnumbermin_products_countnumbermax_products_countnumberads_time_periodtexttraffic_growthlistads_growthlistvisitor_countrytextmain_market_countrieslistmarket_countrieslistexclude_market_countrieslistniche_idnumberlanguageslistcurrencieslisttheme_idslistpixel_idslistexclude_pixel_idslistshopify_app_idslistexclude_shopify_app_idslistis_shopify_plustrue / falsemin_trustpilot_ratingnumbermax_trustpilot_ratingnumbermin_trustpilot_review_countnumbermax_trustpilot_review_countnumbermin_monthly_salesnumbermax_monthly_salesnumbermin_units_soldnumbermax_units_soldnumberhas_tiktoktrue / falseexclude_currencieslistsocial_networkslistshopify_plantext
find_similar_shopsCompetitors of a shop (id or domain)
10 arguments
shoptextlimitnumbersort_bytextordertextoffsetnumberseasontextfiltersobjectmarkettextexclude_shopslistdetailtext
find_winning_productsProducts selling now in a niche
5 arguments
nichetextkeywordslistcountrytextmax_resultsnumberdetailtext
search_productsSearch or browse store products by price, sales, units sold, selling countries, ads, reach, reviews, launch date, currency or shop country
37 arguments
querytextsearch_intextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtextshoptextshop_idtextmin_pricenumbermax_pricenumbermin_monthly_revenuenumbermax_monthly_revenuenumbermin_monthly_units_soldnumbermax_monthly_units_soldnumbermin_active_adsnumbermax_active_adsnumberads_launched_periodtextmin_ads_launchednumbermax_ads_launchednumbermin_ad_sharenumbermax_ad_sharenumbermin_eu_ad_spendnumbermax_eu_ad_spendnumbermin_ratingnumbermin_reviewsnumbersubscriptiontextpartnershiptrue / falseselling_countrieslistmain_selling_countrytextexclude_selling_countrieslistshop_countrieslistcurrencieslistmin_shop_monthly_visitsnumbermax_shop_monthly_visitsnumbershop_created_aftertext
search_products_by_imageFind store products that look like a picture (an image URL or the file), with their shops
12 arguments
image_urltextimage_base64textsort_bytextordertextmax_per_shopnumberfiltersobjectpagenumberlimitnumbersearch_idtextdetailtextoffsetnumbergroup_brandstrue / false
search_shops_by_imageFind the shops selling what a picture shows, with their closest products
7 arguments
image_urltextimage_base64textsearch_idtextlimitnumberoffsetnumbergroup_brandstrue / falseproducts_per_shopnumber
get_productOne product with its full sheet: photos, options and variants
2 arguments
product_idtexturltext
get_product_adsThe Meta ads that link to a product's page
5 arguments
product_idtextstatustextpagenumberlimitnumberdetailtext
analyze_productOne product, its latest ads and a read of its signals
3 arguments
product_idtexturltexttop_adsnumber
product_launch_radarProducts launched recently, ranked by sales or ad pressure
34 arguments
querytextdaysnumberrank_bytextlimitnumberfiltersobjectdetailtextshop_idtextmin_pricenumbermax_pricenumbermin_monthly_revenuenumbermax_monthly_revenuenumbermin_monthly_units_soldnumbermax_monthly_units_soldnumbermin_active_adsnumbermax_active_adsnumberads_launched_periodtextmin_ads_launchednumbermax_ads_launchednumbermin_ad_sharenumbermax_ad_sharenumbermin_eu_ad_spendnumbermax_eu_ad_spendnumbermin_ratingnumbermin_reviewsnumbersubscriptiontextpartnershiptrue / falseselling_countrieslistmain_selling_countrytextexclude_selling_countrieslistshop_countrieslistcurrencieslistmin_shop_monthly_visitsnumbermax_shop_monthly_visitsnumbershop_created_aftertext
create_product_share_linkCreate (or return) the public link to one product
2 arguments
product_idtextconfirmtrue / false
delete_product_share_linkRemove the public link to one product
2 arguments
product_idtextconfirmtrue / false
brief_competitorA compact brief on one competitor (shop id, domain or name)
11 arguments
competitortextsectionslistmax_productsnumbermax_emailsnumbermax_adsnumbershoptextad_rank_windowtextad_rank_sorttextmax_current_ranknumbermin_rank_deltanumbersnapshot_datetext
shop_reportOne report on a shop: its feed, its Facebook pages, Q4 season, a landing page, its ad ranking or its creative tests
19 arguments
shoptextreporttextyearnumberdate_fromtextdate_totexturltextadvertiser_idtextmodetextdaysnumberad_idslistdatetextas_oftextmedia_typetextstatustextkeywordslistsnapshot_datetextpagenumberlimitnumberdetailtext
compare_shopsOne figure of several shops side by side
3 arguments
shopslistmetrictextsnapshot_datetext
market_overviewThe whole market, day by day, or over a Q4 season
5 arguments
kindtextyearnumberdate_fromtextdate_totextlimitnumber
detect_shopify_storeWhether a store runs on Shopify, its theme and the Shopify apps it loads
1 argument
urltext
Ads and media 8
search_adsSearch Meta (Facebook / Instagram) ads by words in the copy, brand or landing page
97 arguments
querytextkeywordslistmedia_typetextcountrytextstatustextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtextcategory_idslistad_countriesobjectmain_countrieslistmin_traffic_growth_percentnumbertraffic_growth_periodtexttraffic_growthlistads_growthlistpage_reach_growthlistad_reach_growthlistad_languagetextlanguagetextad_languageslistctalistshopify_app_idslistexclude_shopify_app_idslistpixel_idslistexclude_pixel_idslisttheme_idslistcreated_aftertextcreated_beforetextlast_seen_aftertextlast_seen_beforetextmin_days_runningnumbermax_days_runningnumbermin_duplicatesnumbermax_duplicatesnumbermax_ad_ordernumberad_rank_modetextad_rank_basistextmax_ad_rank_valuenumbergrowth_ranklistrank_delta_windowtextmin_rank_deltanumbermin_description_lengthnumbermax_description_lengthnumbermin_video_durationnumbermax_video_durationnumbermin_reachnumbermax_reachnumberreach_periodtextmin_agenumbermax_agenumbersextextpartnerstrue / falsemin_trafficnumbermax_trafficnumbermin_active_adsnumbermax_active_adsnumbermin_productsnumbermax_productsnumbermin_best_seller_pricenumbermax_best_seller_pricenumberads_time_periodtextshop_created_aftertextshop_created_beforetextshop_creation_countriesobjectmarketobjectshopify_plustextmin_spendnumbermax_spendnumbercpmnumberspend_periodtextmin_spend_per_pagenumbermax_spend_per_pagenumberspend_per_page_periodtextmin_facebook_likesnumbermax_facebook_likesnumbermin_instagram_followersnumbermax_instagram_followersnumbermin_reach_per_pagenumbermax_reach_per_pagenumberreach_per_page_periodtexttechnologieslisttracked_pageslistmax_ads_per_brandnumbertrend_signaltextactive_onlytrue / falseexclude_formatslistexclude_ad_languageslistage_rangeslistexclude_age_rangeslistexclude_theme_idslistmin_page_ads_launchednumbermax_page_ads_launchednumberpage_ads_launched_periodtextshopify_stores_onlytrue / false
scan_adThe full record of one Meta ad (or of one Google ad or TikTok post)
1 argument
ad_identifiertext
creative_inspiration_packCreative inspiration for a niche
5 arguments
nichetextkeywordslistfocustextmax_adsnumbertrend_signaltext
search_google_ads_librarySearch Google ads
57 arguments
querytextkeywordsliststatustextcountrytextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtextpublished_aftertextpublished_beforetextfirst_seen_aftertextfirst_seen_beforetextmin_days_runningnumbermax_days_runningnumberplatformtextplatformslistaudience_countrytextaudience_countrieslistexclude_audience_countrieslistformattextformatslistwebsite_idtextwebsite_idslisteu_onlytrue / falsemin_reachnumbermax_reachnumbermin_advertiser_reachnumbermax_advertiser_reachnumberremarketingtrue / falseinterest_targetingtrue / falsemain_market_countrieslistexclude_theme_idslistmin_trafficnumbermax_trafficnumbermin_productsnumbermax_productsnumbermin_best_seller_pricenumbermax_best_seller_pricenumbershop_creation_aftertextshop_creation_beforetextshop_creation_countrieslistexclude_shop_creation_countrieslistmarket_countrieslistexclude_market_countrieslistniche_idslistpixelslistexclude_pixelslistshopify_appslistexclude_shopify_appslistthemeslisttraffic_growthlistsnapshot_datetexthide_non_eu_uk_adstrue / falsehide_low_reach_adstrue / falsehide_low_impression_adstrue / false
search_tiktok_librarySearch TikTok ads and organic posts
66 arguments
querytextkeywordslisttypetextcountrytextdomaintexthandletextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtextsearch_intextsearch_areatextitem_typetextstatustextmedia_typetextmedia_typeslistlanguagetextlanguageslistcountrieslistcategorieslisthashtagslisttiktok_page_idtexttiktok_page_idslistwebsite_idtexthas_shop_linkedtextpublished_aftertextpublished_beforetextupdated_aftertextupdated_beforetextmin_days_runningnumbermax_days_runningnumbermin_viewsnumbermax_viewsnumbermin_followersnumbermin_profile_viewsnumbermax_followersnumbermax_profile_viewsnumberprofile_created_aftertextprofile_created_beforetextmin_profile_ads_sharenumbermax_profile_ads_sharenumbermin_profile_postsnumbermax_profile_postsnumbermarket_countrieslistmain_market_countrieslistexclude_market_countrieslistshop_creation_countrieslistexclude_shop_creation_countrieslistmin_trafficnumbermax_trafficnumbermin_productsnumbermax_productsnumbermin_best_seller_pricenumbermax_best_seller_pricenumbershop_creation_aftertextshop_creation_beforetextshopify_appslistexclude_shopify_appslistthemeslistexclude_theme_idslistpixelslistexclude_pixelslistis_pinnedtrue / falsetrend_signaltext
create_ad_share_linkCreate (or return) the public link to one ad
2 arguments
ad_idtextconfirmtrue / false
delete_ad_share_linkRemove the public link to one ad
2 arguments
ad_idtextconfirmtrue / false
write_ad_hooksWrite three short opening lines (hooks) for an ad of a product, for Meta, TikTok or both
7 arguments
nichetextproducttextangletextplatformtextlanguagetextregeneratetextidempotency_keytext
Advertisers and emails 5
search_advertisersSearch advertisers (Facebook pages)
26 arguments
querytextkeywordslistsearch_intextcountrytextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtextcategory_idslisttimeframetextexclude_age_rangeslistmarket_countrieslistmain_market_countrieslistexclude_market_countrieslistshop_creation_countrieslistexclude_shop_creation_countrieslistmin_productsnumbermax_productsnumbershop_creation_aftertextshop_creation_beforetextshopify_appslistexclude_shopify_appslistthemeslistexclude_theme_idslist
scan_advertiserOne advertiser's record, or its live ads and reach day by day
4 arguments
advertiser_idtextviewtextdaysnumbersnapshot_datetext
search_emailsSearch brands' marketing emails by words in the subject, sender or content
11 arguments
querytextshoptextcampaign_typetextsort_bytextordertextpagenumberlimitnumberfiltersobjectdetailtexttimeframetextintenttext
get_email_htmlThe raw HTML of one email (use search_emails first to find the id)
4 arguments
email_idtextinclude_htmltrue / falseshoptexthtml_partnumber
analyze_shop_emailsA shop's email strategy
2 arguments
shoptextmax_emailsnumber
Tracked brands 14
list_tracked_brandsThe brands you track, with their live ad counters
6 arguments
pagenumberlimitnumberfolder_idslistnametextsort_bytextfolder_idnumber
add_to_brandtrackerStart tracking a brand
5 arguments
facebook_page_idtextwebsite_idtextshop_idtextdomaintextfolder_idnumber
delete_from_brandtrackerStop tracking a brand
3 arguments
brandtracker_idtextconfirmtrue / falseworkspace_link_idnumber
list_brandtracker_foldersYour tracker folders
create_brandtracker_folderCreate a tracker folder
1 argument
nametext
rename_brandtracker_folderRename a tracker folder
2 arguments
folder_idnumbernametext
delete_brandtracker_folderDelete a tracker folder
3 arguments
folder_idnumberactiontextconfirmtrue / false
move_tracked_brandsMove tracked brands into a folder (folder_id=null takes them out of any folder)
3 arguments
brandtracker_idslistfolder_idnumberworkspace_link_idslist
get_brand_activityWhat a tracked brand did across Meta, TikTok, Google and email
11 arguments
brandtracker_idtextbrandtextviewtextsourcetextsincetextuntiltextdaytexttypeslistpagenumberlimitnumberdetailtext
analyze_tracked_brandA deep look at one tracked brand
4 arguments
brandtracker_idtextbrandtextsnapshot_datetextdetailtext
analyze_brand_changesWhat changed for a tracked brand over a period (1d, 7d, 14d, 30d; rank gained is read over 7d for 1d, hooks over 30d for 14d, creative tests are the latest)
6 arguments
brandtracker_idtextbrandtextperiodtextfocustextsnapshot_datetextdetailtext
get_brandtracker_scaling_adsThe ads of a tracked brand that gained the most rank, with their rank history
32 arguments
brandtracker_idtextbrandtextad_rank_windowtextad_rank_sorttextmax_current_ranknumbermin_rank_deltanumberpagenumberlimitnumberdetailtextfacebook_page_idtextall_facebook_pagestrue / falseordertextgrowth_ranklistquerytextkeywordslistmedia_typetextstatustextcreated_aftertextcreated_beforetextmin_days_runningnumbermax_days_runningnumbermin_duplicatesnumbermax_duplicatesnumberad_languagetextad_languageslistad_countriesobjectmain_countrieslistctalistad_copy_hasheslistpartnerstrue / falsepartner_idslisthide_low_impressionstrue / false
get_brandtracker_transcriptsVideo scripts of a tracked brand, grouped by text
9 arguments
brandtracker_idtextbrandtexttime_periodtextpagenumberlimitnumbereu_onlytrue / falseordertextsort_bytextsnapshot_datetext
daily_radarDaily digest across your tracked brands
4 arguments
folder_idslistfocustextevent_typeslistfolder_idnumber
Boards 14
list_boardsYour boards
8 arguments
scopetextstatetextkindtextsurfacetextparent_board_idtextroot_onlytrue / falsepagenumberlimitnumber
get_boardOne board
1 argument
board_idtext
create_boardCreate a board
6 arguments
nametextkindtextsurfacetextdescriptiontextvisibilitytextparent_board_idtext
update_boardRename a board, change its description or its visibility
4 arguments
board_idtextnametextdescriptiontextvisibilitytext
move_boardMove a board under a folder board (parent_board_id=null moves it to the top level)
2 arguments
board_idtextparent_board_idtext
archive_boardArchive a board and everything under it (restore_board brings it back)
2 arguments
board_idtextconfirmtrue / false
restore_boardRestore an archived board
1 argument
board_idtext
list_board_itemsThe items saved on a board
3 arguments
board_idtextpagenumberlimitnumber
find_saved_itemsSearch everything you saved, on every board and in your favorites
13 arguments
querytextsource_typeslistboard_idtextscopetextstatetextsaved_fromtextsaved_totextsort_bytextordertextpagenumberlimitnumberinclude_itemstrue / falsedetailtext
add_board_itemSave an item on a collection board
5 arguments
board_idtextsource_typetextsource_idtextsource_indextextpositionnumber
move_board_itemMove a saved item to another board
4 arguments
board_idtextitem_idtexttarget_board_idtextpositionnumber
remove_board_itemRemove a saved item from a board
3 arguments
board_idtextitem_idtextconfirmtrue / false
create_board_share_linkCreate a public link to a board
2 arguments
board_idtextconfirmtrue / false
delete_board_share_linkRemove the public links to a board
2 arguments
board_idtextconfirmtrue / false
Favorites 10
list_favoritesYour saved ads, shops or emails
6 arguments
kindtextscopetextfolder_idtextpagenumberlimitnumberdetailtext
add_favorite_itemSave an ad, a shop or an email
4 arguments
kindtextitem_idtextscopetextfolder_idtext
move_favorite_itemMove a saved favorite to a folder (folder_id=null moves it out of any folder)
4 arguments
kindtextfavorite_idtextscopetextfolder_idtext
remove_favorite_itemRemove a saved favorite, by its own id (favorite_id) or by the id of the saved record (item_id)
5 arguments
kindtextscopetextfavorite_idtextitem_idtextconfirmtrue / false
create_favorite_folderCreate a favorite folder
4 arguments
kindtextnametextscopetextparent_idtext
update_favorite_folderRename a favorite folder, or move it (move=true with parent_id, null for the top level)
6 arguments
kindtextfolder_idtextscopetextnametextparent_idtextmovetrue / false
delete_favorite_folderDelete a favorite folder
6 arguments
kindtextfolder_idtextmodetextscopetexttarget_folder_idtextconfirmtrue / false
set_favorite_folder_visibilityMake a favorite folder private or shared
4 arguments
kindtextfolder_idtextvisibilitytextscopetext
create_favorite_folder_share_linkCreate a public link to a favorite folder
4 arguments
kindtextfolder_idtextscopetextconfirmtrue / false
delete_favorite_folder_share_linkRemove the public links to a favorite folder
4 arguments
kindtextfolder_idtextscopetextconfirmtrue / false
Account 2
usage_getYour plan, its credits and how many are left
check_creditsHow many credits you have left this month (same answer as usage_get)