API Reference
Search data with built-in piracy labeling, structured piracy intelligence, and integrations that put creator protection inside your product — from a copy-paste widget to a full platform partnership.
Read https://branditscan.com/developers/guide.md and integrate the BranditScan protection funnel into this codebase: the funnel module on every logged-in dashboard page, the nav badge, the dashboard banner, and a Takedowns page per the guide's sections 4-7. Before writing code, ask me for: the template variable holding the logged-in creator's stagename, our BranditScan affiliate slug, and where the nav / dashboard / routes live. Keep the module and the data-bs-* attribute contract exactly as written in the guide. If I ask for a lighter integration (page only, or a single iframe), follow the guide's Appendix instead of the full step order. When done, verify your work against the guide's QA checklist (section 15).
How access works
Everything except the Leak Check widget is scoped per partner — no open keys
The Leak Check widget is live and free for everyone — copy the snippet and go. Everything else — the APIs and the Self Submissions Widget — is available on request: we scope access to your use case instead of handing out open keys. Getting set up is fast:
Creators love our products. Boost your brand.
Platforms like YourVids, LoyalFans, Aylo, and CosmoPayment put BranditScan protection in front of their creators. Give yours the tools they already ask for:
And you get paid: earn commission on every subscription your integration produces.
Google Search API
Live SERP data — web, images & videos, piracy-labeled
- A scoped API key + base URL, issued after approval — email your use case: what you're building and the monthly volume you expect. Credentials typically within 1 working day.
Live Google SERP data from the same engine that powers our scanners — web, image, and video sections with position data. Every result is checked against the BranditScan Entry database of 5,000,000+ pirate sites, so piracy labeling comes built in.
/v1/search/googleWeb results — the "All" section/v1/search/google/imagesImage results, with thumbnail + source page/v1/search/google/videosVideo results, with duration + platform| Parameter | Description |
|---|---|
q | Required. The search query. |
num | Results per page, 10–100. Default 20. |
page | Result page. Default 1. |
hl | Interface language, e.g. en. |
gl | Country to search from, e.g. us. |
Sample request
curl "$BASE_URL/v1/search/google?q=jane+doe+leaks&num=50&hl=en&gl=us" \ -H "Authorization: Bearer $API_KEY"
{
"query": "jane doe leaks",
"engine": "google",
"section": "web",
"total_results": 1840000,
"results": [
{
"position": 1,
"title": "Jane Doe Leaked Videos — Watch Free",
"link": "https://superpirate.xyz/jane-doe",
"domain": "superpirate.xyz",
"snippet": "Watch Jane Doe leaked videos free in HD...",
"piracy": {
"is_pirate": true,
"category": "video cloud",
"tracked_leaks": 128411
}
},
{
"position": 2,
"title": "Jane Doe (@janedoe) — Official",
"link": "https://onlyfans.com/janedoe",
"domain": "onlyfans.com",
"snippet": "Official page of Jane Doe.",
"piracy": { "is_pirate": false }
}
]
}
Bing Search API
Identical contract — swap the engine segment
- A scoped API key + base URL — email your use case and expected volume; one request can cover several engines. Credentials typically within 1 working day.
The same contract as the Google Search API, running against Bing — web, image, and video sections with identical parameters (q, num, page, hl, gl) and the same per-result piracy labeling. Swap the engine segment and keep your integration code.
/v1/search/bingWeb results — the "All" section/v1/search/bing/imagesImage results/v1/search/bing/videosVideo resultscurl "$BASE_URL/v1/search/bing?q=jane+doe+leaks&num=50" \ -H "Authorization: Bearer $API_KEY"
Yandex Search API
Identical contract — Eastern Europe & CIS coverage
- A scoped API key + base URL — email your use case and expected volume; one request can cover several engines. Credentials typically within 1 working day.
Yandex coverage matters when your audience — or the piracy targeting it — lives in Eastern Europe and CIS markets. Same request contract and response shape as Google and Bing: web, image, and video sections, position data, and per-result piracy labeling against our Entry database.
/v1/search/yandexWeb results — the "All" section/v1/search/yandex/imagesImage results/v1/search/yandex/videosVideo resultscurl "$BASE_URL/v1/search/yandex?q=jane+doe+leaks&num=50" \ -H "Authorization: Bearer $API_KEY"
Piracy Data API
The dataset behind the Brandit Atlas — 5,000,000+ pirate sites
- A scoped API key + base URL — email your use case; bulk exports and webhook feeds are available for approved partners. Credentials typically within 1 working day.
Structured piracy intelligence from the largest takedown operation in the creator space — the dataset behind the Brandit Atlas. Domain reputation, threat ratings, tracked-leak volumes, category data, and takedown capability per site. Classify any domain or URL in one call.
/v1/piracy/domains/{domain}Full intelligence profile for a domain/v1/piracy/check?url={url}Classify a full URL — is this a pirate page?Sample request
curl "$BASE_URL/v1/piracy/domains/fapello.com" \ -H "Authorization: Bearer $API_KEY"
{
"domain": "fapello.com",
"is_pirate": true,
"category": "image host",
"threat": { "level": 4, "label": "Critical" },
"tracked_leaks": 1284110,
"reported_infringements": 96731,
"capabilities": {
"source_removal": true,
"google_delisting": true
},
"description": "High-volume aggregator redistributing paywalled creator content..."
}
Leak Check Widget — iframe embed
No key, no signup, no approval — copy the snippet and ship it
The only thing on this page you don't need to email us for. A live piracy scanner your visitors use right on your page: they type a stage name, we run a real-time Google scan and check every result against our database of 5,000,000+ pirate sites. Free to embed anywhere HTML works.
<!-- BranditScan Leak Check widget -->
<iframe src="https://branditscan.com/embed/leak-check" title="Free Leak Check by BranditScan" style="display:block;width:100%;max-width:960px;margin:0 auto;height:620px;border:0;border-radius:24px;background:url(https://branditscan.com/front/lp/assets/images/leak-widget-spinner.svg) no-repeat center 140px;" scrolling="no" loading="lazy"></iframe>
<script>
window.addEventListener("message", function (e) {
if (e.origin !== "https://branditscan.com" || !e.data || e.data.type !== "bs-leak-check:height") return;
document.querySelectorAll("iframe[src^='https://branditscan.com/embed/leak-check']").forEach(function (f) {
if (f.contentWindow === e.source) f.style.height = Math.ceil(e.data.height) + "px";
});
});
</script>
| Parameter | What it does |
|---|---|
aff | Your BranditScan affiliate slug. Signups from the widget are credited to you — see the earnings note below. |
stagename | Prefills the search and runs it immediately on load, e.g. ?stagename=janedoe. Results are cached, so repeat loads are instant. |
rail | Pins the side visual: odometer (money counter), sweep (before/after), cases (sliding case studies) or loss (average piracy loss). Omit for random rotation per load. |
border | border=0 turns the animated rainbow shell border off (on by default). |
blur | blur=0 renders result images unblurred by default (they're NSFW-blurred with click-to-reveal out of the box). |
t | Optional — only if you want SSO (partner platforms): pass your signed Self Submissions Widget token and the CTAs flip to a one-click "Open my BranditScan" sign-in for members with a BranditScan account you created (new tab, no password, zero extra code). Absent or invalid — nothing changes. |
postMessage API
The widget talks to your page over postMessage, so you can auto-size the iframe and drive scans from your own UI:
// OUT — sent by the widget on every layout change (auto-height):
// { "type": "bs-leak-check:height", "height": 1240 }
// IN — prefill + run a scan from your own page:
var frame = document.querySelector("iframe[src*='/embed/leak-check']");
frame.contentWindow.postMessage(
{ type: "bs-leak-check:scan", stagename: "jane doe" },
"https://branditscan.com"
);
Live demo — embedded on your site
This is the real widget, live on this page — type a stage name, or hit Run sample scan to see it work end-to-end (uses the widget's postMessage API).
Conversion Funnel — connect the widgets to your UI
Two components, one hidden data feed — a Takedowns menu item, a banner, and a page that converts
- Nothing for the Leak Check side — the scanner, the hidden module, the nav badge and the banner work immediately, no key.
- A Self Submissions signing secret for the free-takedowns card — email us when you start building (same-day, free) and include your production domain plus your local dev hosts (localhost, *.test) so the widget renders in your dev environment too.
- Your affiliate slug (optional) for signup attribution — free BranditScan account, it's in your Earnings Hub.
You get two embeddable components — use both or just one.
Scans a name live — leaks, traffic-loss %, the stolen images. Run it visible, or hidden as a data feed.
Free — no key, works todayReal DMCA takedowns, filed from your page — we file, track and sign them.
Free — signing secret requiredUse both together (recommended — that's the funnel below) or either one on its own.
The preferred implementation
Give the widgets their own section. Create a dedicated page in your app where both widgets live, point a menu item at it, and — optionally — feed it traffic with a dashboard banner. Live on partner platforms today:
Runs silently: an invisible iframe pulls the creator's piracy data and caches it in their browser for 24h — all frontend, no backend, no database. Every surface below renders from it.
A new page in your app — file a takedown free or go automated, side by side, with the full leak report loading underneath so creators immediately see their leaks.
Powered by the module: it fills the badge with the creator's own live number — "▲ 18%" traffic loss — right in your nav, and points at your new page. Name it Takedowns, Leaks or Remove Leaks.
Also powered by the module: it personalizes the banner with their own leaked images, blurred, on the dashboard or settings page — clicking straight into the page.
No database, nothing to poll — one hidden load per creator per day. The module below does all of it.
Build it — step by step
Four pastes, in this order. Or your own order — after step 1 the data is yours (see the payload reference below the steps).
Two script tags, in your main layout: every page that shows the nav item or the banner needs the module available, so include it globally. What it does: when there's no fresh data for the creator, it loads the Leak Check widget in an invisible iframe, silently reads the scan result the widget posts, caches it in the creator's browser for 24 hours, and removes the iframe. Nothing is saved to your backend or database — the data lives on the frontend, and any surface can render from it: the nav badge, the banner, or anything else you want to build with it. Every step after this is just placing HTML hooks.
<!-- Once, on every logged-in dashboard page: the config + the module -->
<script>
window.BS_FUNNEL = {
stagename: "SARAH", // <- the logged-in creator's stagename (template it server-side)
aff: "your-affiliate-slug" // <- optional: your BranditScan affiliate slug
};
</script>
<script src="/js/bs-funnel.js" defer></script> <!-- the module: copy it from the block below -->
/* bs-funnel.js — BranditScan protection funnel, v1.
Config: window.BS_FUNNEL = { stagename, aff } (set before this runs). */
(function () {
'use strict';
var cfg = window.BS_FUNNEL || {};
var STAGENAME = (cfg.stagename || '').trim();
if (!STAGENAME) return; // viewers, no-stagename users: do nothing
var ORIGIN = 'https://branditscan.com';
var CACHE_KEY = 'bs-leak-check:' + STAGENAME.toLowerCase();
var DAY = 24 * 60 * 60 * 1000;
/* ---------- pub/sub ---------- */
function publish(result) {
window.bsLeakData = result; // for late-joining code
document.dispatchEvent(new CustomEvent('bs-leak-data', { detail: result }));
}
/* ---------- normalization ---------- */
function toResult(d) {
// Google-Images pirated thumbs first, then per-site samples as fill —
// deduped, capped. Covers creators whose Google-Images page is clean
// but whose proof images live on the pirate sites themselves.
var thumbs = (d.thumbs || []).concat(d.samples || [])
.filter(function (src, i, all) { return all.indexOf(src) === i; })
.slice(0, 12);
return {
standing: d.standing,
traffic: d.traffic || null, // { pct, surface: 'web'|'images' }
pirates: d.pirates || 0,
domains: (d.domains || []).slice(0, 6),
thumbs: thumbs,
estimatedLoss: d.estimatedLoss || null,
at: Date.now()
};
}
/* ---------- verified accept (probe + visible embed share this) ---------- */
function isOwnResult(event, frame) {
if (event.origin !== ORIGIN) return false;
if (!frame || !frame.contentWindow || event.source !== frame.contentWindow) return false;
var d = event.data || {};
if (d.type !== 'bs-leak-check:result') return false;
// Poisoning guard: only the logged-in creator's own name may be cached.
return (d.stagename || '').toLowerCase() === STAGENAME.toLowerCase();
}
function accept(data) {
var result = toResult(data);
try { localStorage.setItem(CACHE_KEY, JSON.stringify(result)); } catch (e) { /* storage blocked — in-memory only */ }
publish(result); // latest verified message wins
}
/* ---------- the hidden probe ---------- */
function embedUrl() {
return ORIGIN + '/embed/leak-check?branding=0&border=0'
+ (cfg.aff ? '&aff=' + encodeURIComponent(cfg.aff) : '')
+ '&stagename=' + encodeURIComponent(STAGENAME);
}
function startProbe() {
var frame = document.createElement('iframe');
frame.src = embedUrl();
frame.referrerPolicy = 'no-referrer'; // scans 403 silently without this
frame.style.cssText = 'position:absolute;width:2px;height:2px;left:-9999px;top:0;border:0;';
frame.setAttribute('aria-hidden', 'true');
frame.setAttribute('tabindex', '-1');
var gotFirst = false;
function teardown() {
window.removeEventListener('message', onMsg);
if (frame.parentNode) frame.parentNode.removeChild(frame);
}
function onMsg(event) {
if (!isOwnResult(event, frame)) return;
accept(event.data);
if (!gotFirst) {
gotFirst = true;
setTimeout(teardown, 15000); // linger: catch the enriched samples re-post
}
}
window.addEventListener('message', onMsg);
setTimeout(function () { if (!gotFirst) teardown(); }, 180000); // fail silent
document.body.appendChild(frame);
}
/* ---------- consumers ---------- */
document.addEventListener('bs-leak-data', function (e) { renderAll(e.detail); });
function renderAll(r) {
if (!r || !r.standing) return;
renderNavBadge(r);
renderBanner(r);
renderTakedownsPage(r);
}
/* Nav badge: red % pill when at risk, green check for members, nothing
when clean. Compact by design — long badges truncate nav labels. */
function renderNavBadge(r) {
document.querySelectorAll('[data-bs-nav-badge]').forEach(function (slot) {
if (slot.dataset.done) return;
if (r.standing === 'at_risk') {
slot.textContent = (r.traffic && r.traffic.pct > 0)
? '\u25B2 ' + Math.round(r.traffic.pct) + '%'
: r.pirates + ' leaks';
slot.className = 'bs-badge bs-badge--alert';
slot.hidden = false;
} else if (r.standing === 'account') {
slot.textContent = '\u2713';
slot.className = 'bs-badge bs-badge--ok';
slot.hidden = false;
}
slot.dataset.done = '1'; // decide once per pageview
});
}
/* Banner: server-rendered generic copy is the default state; this only
upgrades it when there is something personal to say. */
function renderBanner(r) {
var el = document.querySelector('[data-bs-banner]');
if (!el || el.dataset.done) return;
el.dataset.done = '1';
function setText(sel, text) {
var n = el.querySelector(sel);
if (n) { n.textContent = text; n.hidden = false; }
}
if (r.standing === 'account') {
el.classList.add('bs-banner--protected');
setText('[data-bs-banner-headline]', 'Your content is protected');
setText('[data-bs-banner-sub]',
'BranditScan is watching your name 24/7 \u2014 new leaks get found and taken down for you.');
return;
}
if (r.standing !== 'at_risk' || r.pirates < 1) return; // keep the generic pitch
var name = (el.getAttribute('data-user-name') || '').trim();
setText('[data-bs-banner-headline]',
(name ? name + ', we' : 'We') + ' found your content on pirate sites.');
setText('[data-bs-banner-sub]',
'Take it down free \u2014 takedowns are covered for every creator.');
if (r.domains.length) {
setText('[data-bs-banner-domains]',
'Found on: ' + r.domains.slice(0, 2).join(' \u00B7 ')
+ (r.domains.length > 2 ? ' \u00B7 +' + (r.domains.length - 2) + ' more' : ''));
}
var statNum = el.querySelector('[data-bs-banner-stat]');
var statLabel = el.querySelector('[data-bs-banner-stat-label]');
if (statNum && statLabel) {
if (r.traffic && r.traffic.pct > 0) {
statNum.textContent = '+' + Math.round(r.traffic.pct) + '%';
statLabel.textContent = 'revenue to reclaim';
} else {
statNum.textContent = String(r.pirates);
statLabel.textContent = 'leaks to remove';
}
statNum.hidden = statLabel.hidden = false;
}
var strip = el.querySelector('[data-bs-banner-thumbs]');
if (strip && r.thumbs.length) renderThumbStrip(strip, r.thumbs);
}
/* Leaked-image strip: preload off-DOM, render only survivors (hotlinked
images die unpredictably), favicon-badge each tile, blur via YOUR css.
Tiles land in a .bs-leak-track; with 4+ survivors the set is duplicated
and the track tagged --loop, so the CSS marquee slides it seamlessly.
Too few tiles = no duplication, no animation — a static row. */
function renderThumbStrip(strip, urls) {
var loaded = [];
var pending = urls.length;
var rendered = false;
function makeTile(src, isClone) {
var tile = document.createElement('span');
tile.className = 'bs-leak-tile';
if (isClone) tile.setAttribute('aria-hidden', 'true');
var img = document.createElement('img');
img.src = src;
img.referrerPolicy = 'no-referrer';
img.alt = '';
tile.appendChild(img);
try {
var host = new URL(src).hostname.replace(/^www\./, '');
var fav = document.createElement('img');
fav.className = 'bs-leak-tile__favicon';
fav.src = 'https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&size=32&url=https://' + host;
fav.onerror = function () { fav.remove(); };
tile.appendChild(fav);
tile.title = host;
} catch (e) {}
return tile;
}
function render() {
if (rendered || !loaded.length) return;
rendered = true;
var set = loaded.slice(0, 8);
var track = document.createElement('div');
track.className = 'bs-leak-track' + (set.length >= 4 ? ' bs-leak-track--loop' : '');
set.forEach(function (src) { track.appendChild(makeTile(src, false)); });
if (set.length >= 4) {
set.forEach(function (src) { track.appendChild(makeTile(src, true)); });
}
strip.appendChild(track);
strip.hidden = false;
}
urls.forEach(function (src) {
var probe = new Image();
probe.referrerPolicy = 'no-referrer';
probe.onload = function () { loaded.push(src); if (--pending === 0) render(); };
probe.onerror = function () { if (--pending === 0) render(); };
probe.src = src;
});
setTimeout(render, 8000); // straggler cutoff: show what loaded
}
/* Takedowns page: fill the automation card's %, decide the leak embed
once (a late probe result must never yank a loaded widget). */
function renderTakedownsPage(r) {
var pct = document.querySelector('[data-bs-pct]');
if (pct && r.standing === 'at_risk' && r.traffic && r.traffic.pct > 0) {
pct.textContent = '+' + Math.round(r.traffic.pct) + '%';
}
var frame = document.getElementById('bs-leakcheck');
if (!frame || frame.dataset.decided || frame.getAttribute('src')) return;
frame.dataset.decided = '1';
var section = document.querySelector('[data-bs-leak-section]');
if (r.standing === 'good' || r.standing === 'account') {
if (section) section.hidden = true; // nothing to look at; saves scan quota
} else if (frame.dataset.srcPrefilled) {
frame.src = frame.dataset.srcPrefilled; // at_risk: auto-run the full report
}
}
/* ---------- iframe heights + visible-embed harvesting ---------- */
window.addEventListener('message', function (e) {
if (e.origin !== ORIGIN) return;
var d = e.data || {};
var lk = document.getElementById('bs-leakcheck');
var tw = document.getElementById('bs-takedowns');
if (d.type === 'bs-leak-check:height' && lk && e.source === lk.contentWindow) {
lk.style.height = Math.ceil(d.height) + 'px';
}
if (d.type === 'bs-takedowns:height' && tw && e.source === tw.contentWindow) {
tw.style.height = Math.ceil(d.height) + 'px';
}
// The visible embed keeps refreshing the cache for the whole visit —
// including manual re-scans of the creator's OWN name (others rejected).
if (lk && isOwnResult(e, lk)) accept(d);
});
/* ---------- boot ---------- */
var cached = null;
try { cached = JSON.parse(localStorage.getItem(CACHE_KEY) || 'null'); } catch (e) {}
var visibleEmbed = document.getElementById('bs-leakcheck');
if (cached && (Date.now() - cached.at) < DAY) {
publish(cached); // instant, zero network
} else if (visibleEmbed && visibleEmbed.dataset.srcPrefilled) {
visibleEmbed.dataset.decided = '1'; // no data: the VISIBLE embed is the probe
visibleEmbed.src = visibleEmbed.dataset.srcPrefilled;
} else {
startProbe(); // any other page: hidden probe
}
})();
Two rules already baked in (skipping them costs every integrator a day): referrerpolicy="no-referrer" on every frame — scans 403 silently without it — and the probe parks off-screen, never display:none, never loading="lazy".
A new page in your app — the menu item and banner will point here. Best practice is showing both ways to act, side by side: Submit free — the Self Submissions widget, unlimited; smaller and mid-size creators happily stay on it forever. Go automated — links out to BranditScan with your aff code; typically what bigger creators pick once the free path has shown them what's out there. The full Leak Check report runs underneath.
How the pieces fit — your design, your copy; the screenshots above are inspiration, not a template:
- The "go automated" card is a plain link out to BranditScan with your
affcode — nothing to wire. - The "submit free" card toggles the Self Submissions iframe right below it — hidden until that click, so it never loads for visitors who don't ask for it.
- The Leak Check report loads underneath automatically — creators land on the page and immediately see their leaks (the module auto-runs it for at-risk creators and hides it for clean or already-protected ones).
<!-- /takedowns — two simple cards, style them your way (see the screenshots) -->
<div class="cards">
<div class="card"> <!-- FREE — self submission -->
<h4>Submit takedowns — free</h4>
<p>Paste a stolen link — a formal DMCA notice gets filed for you. Unlimited.</p>
<a href="#takedown-widget" data-bs-open-takedowns>Submit a link</a>
</div>
<div class="card"> <!-- AUTOMATED — your aff link -->
<h4>Want it fully automated?</h4>
<p>24/7 scanning and takedowns handled for you — reclaim up to
<b data-bs-pct>+22%</b> of your traffic.</p>
<a href="https://branditscan.com/register?aff=your-affiliate-slug"
target="_blank" rel="noopener">Get protected</a>
</div>
</div>
<!-- Self Submissions widget — hidden until the free card is clicked; the
iframe never loads for visitors who don't ask for it. Signing secret:
email help@branditscan.com when you START building (guide section 5.2). -->
<section id="takedown-widget" hidden>
<iframe id="bs-takedowns" data-src="https://branditscan.com/embed/takedowns?t=TOKEN&funnel=off"
referrerpolicy="no-referrer" scrolling="no" style="width:100%;border:0;height:520px;"></iframe>
</section>
<script>
/* the free card's CTA reveals the widget and loads its iframe */
document.addEventListener('click', function (e) {
var t = e.target.closest('[data-bs-open-takedowns]');
if (!t) return;
e.preventDefault();
var s = document.getElementById('takedown-widget');
var f = document.getElementById('bs-takedowns');
s.hidden = false;
if (f && !f.getAttribute('src') && f.dataset.src) f.src = f.dataset.src;
s.scrollIntoView();
});
</script>
<!-- Leak Check report — loads by itself; the module decides once per pageview:
at risk -> auto-runs, creators see their leaks the moment they land
clean / protected -> this WHOLE SECTION stays hidden (and those creators
get no nav badge either — silence is the reward)
no data yet -> loads prefilled and doubles as that day's probe -->
<section data-bs-leak-section>
<iframe id="bs-leakcheck"
data-src-prefilled="https://branditscan.com/embed/leak-check?aff=your-affiliate-slug&border=0&stagename=SARAH"
referrerpolicy="no-referrer" scrolling="no" style="width:100%;border:0;height:600px;"></iframe>
</section>
Signing secret (see "What you'll need" up top) not arrived yet? Ship the automated card alone — never show "Submit free" before the page can deliver it.
One nav link plus one empty span — the module fills it from the hidden scan. Name it Takedowns, Leaks or Remove Leaks.
<a href="/takedowns"> Takedowns <span data-bs-nav-badge hidden></span> </a> <!-- the module fills it: at risk -> red "▲ 18%" · member -> green ✓ · clean -> nothing -->
Server-render your generic pitch; the module upgrades it in place when the creator is at risk — name headline, domains, green stat, their own leaked images (blurred) — and recolors it to "protected" for members. Works on the dashboard, settings, or an empty state.
A live sample — and exactly what the snippet below renders once the module fills it. Hover pauses the strip. Sample images; on a real dashboard these are the creator's own leaked images, blurred.
<!-- Server-render your generic pitch; the module upgrades it in place when
the cache has something personal to say — the sample above is exactly
what this renders for an at-risk creator. One [data-bs-banner] per
page: dashboard, settings, an empty state... -->
<div class="bs-banner" data-bs-banner data-user-name="Sarah"
onclick="if (!event.target.closest('a')) location.href='/takedowns'">
<span class="bs-banner__stat">
<b data-bs-banner-stat hidden></b> <!-- "+18%" (green — opportunity framing) -->
<i data-bs-banner-stat-label hidden></i> <!-- "revenue to reclaim" -->
</span>
<h3 data-bs-banner-headline>Protect your content</h3>
<p data-bs-banner-sub>Pirate sites repost creator content within days of upload.
Run a free scan and see what's out there with your name on it.</p>
<p data-bs-banner-domains hidden></p> <!-- "Found on: site1 · site2 · +2 more" -->
<div data-bs-banner-thumbs hidden></div> <!-- their leaked images: blurred sliding tiles -->
<a href="/takedowns">Check my name →</a>
<small>Powered by BranditScan</small>
</div>
<style>
/* The banner above, verbatim — restyle freely, every class name is yours. */
.bs-banner { position: relative; overflow: hidden; cursor: pointer; border-radius: 14px;
border: 1px solid rgba(233, 162, 0, .42); background: #fffdf2;
padding: 18px 128px 14px 20px; }
.bs-banner h3 { margin: 0 0 3px; font-size: 15.5px; }
.bs-banner p { margin: 0; font-size: 12.5px; line-height: 1.55; color: #606662; }
.bs-banner [data-bs-banner-domains] { margin-top: 6px; font-size: 11.5px; color: #8c928e; }
.bs-banner__stat { position: absolute; top: 18px; right: 20px; text-align: right;
color: #1f9d5b; font-size: 22px; line-height: 1.1; font-weight: 600; }
.bs-banner__stat i { display: block; font-style: normal; font-weight: 400;
font-size: 10.5px; color: #7a807c; margin-top: 2px; }
.bs-banner > a { display: inline-block; margin-top: 10px; font-size: 12.5px;
font-weight: 600; color: #7f42fd; text-decoration: none; }
.bs-banner > small { display: block; margin-top: 10px; font-size: 10.5px; color: #969c98; }
.bs-banner--protected { border-color: rgba(31, 157, 91, .4); background: #f3fbf6; }
/* The proof strip — the module fills [data-bs-banner-thumbs] with a
.bs-leak-track and duplicates the tiles, so -50% loops seamlessly. */
[data-bs-banner-thumbs] { margin-top: 12px; overflow: hidden;
-webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); }
.bs-leak-track { display: flex; width: max-content; }
.bs-leak-track--loop { animation: bsLeakSlide 32s linear infinite; }
[data-bs-banner-thumbs]:hover .bs-leak-track { animation-play-state: paused; }
.bs-leak-tile { position: relative; flex-shrink: 0; width: 64px; height: 64px; margin-right: 8px;
border: 2px solid #e5484d; border-radius: 10px; overflow: hidden; }
.bs-leak-tile img:first-child { width: 100%; height: 100%; object-fit: cover;
filter: blur(7px); transform: scale(1.15); } /* the blur is non-negotiable */
.bs-leak-tile__favicon { position: absolute; right: 3px; bottom: 3px; width: 15px; height: 15px;
border-radius: 4px; background: #fff; padding: 1px; }
@keyframes bsLeakSlide { to { transform: translateX(-50%); } }
@media (max-width: 560px) {
.bs-banner { padding-right: 20px; }
.bs-banner__stat { position: static; display: block; margin-bottom: 6px; }
}
@media (prefers-reduced-motion: reduce) { .bs-leak-track--loop { animation: none; } }
</style>
bs-leak-data event: put the % on the earnings page, in the onboarding checklist, on a settings row. The full payload reference is right below.
The data — bs-leak-check:result
When a scan completes, the widget posts everything your UI needs. The module verifies, normalizes and caches it (24h), then fires one bs-leak-data event every surface listens to:
| Field | What it powers |
|---|---|
standing | The state machine: at_risk (pirates found) · good (clean) · account (already a BranditScan member — no scan data is sent, render "Protected", never upsell) |
traffic.pct | The headline number — % of the creator's search traffic going to pirate sites. The nav badge ("▲ 18%") and the banner stat ("+18% revenue to reclaim") |
pirates | Fallback headline when there's no traffic %: "6 leaks to remove" |
domains ≤6 | The proof line — "Found on: site1 · site2 · +3 more" |
thumbs + samples ≤50 each | The creator's actual leaked images (Google Images + pulled straight off the pirate sites). Render blurred, always. samples arrives in a second, enriched re-post of the same result a few seconds later — the module handles it |
estimatedLoss | "≈ $12.4K/yr at risk" — formatted string; render only when it starts with $ |
stagename | Echoed on every result — the verification key. The module only caches results matching the logged-in creator's name, so a manual scan of someone else can never poison the cache |
Live demo — a mock creator dashboard
It fires on its own: a sample result runs through the module's exact pipeline — the badge lands on the nav item, the banner personalizes with the creator's leaked images. Everything is fed by the module from its 24h browser cache — all front-end, no backend — and both the badge and the banner exist to push traffic to your Takedowns page.
Going deeper — higher self-submission volume & custom skins on the widget, server-side scan data (no iframes), one-click SSO — is the credentialed partner tier: book a call or email us.
Agency Leak Check Widget — roster scans
The Leak Check widget, rebuilt for agencies — multiple models, one embed
Your users manage rosters, not single names? This is the same live scanner as the Leak Check Widget, adjusted for agencies: they add every model's stage name, the widget scans each one against our database of 5,000,000+ pirate sites and rolls it up into an agency report — models at risk, revenue at risk across the roster, the sites hitting the most models, and a per-model drill-down. Free to embed anywhere HTML works, no key needed.
<!-- BranditScan Agency Leak Check widget -->
<iframe src="https://branditscan.com/embed/agency-leak-check" title="Agency Leak Check by BranditScan" style="display:block;width:100%;max-width:960px;margin:0 auto;height:620px;border:0;border-radius:24px;background:url(https://branditscan.com/front/lp/assets/images/leak-widget-spinner.svg) no-repeat center 140px;" scrolling="no" loading="lazy"></iframe>
<script>
window.addEventListener("message", function (e) {
if (e.origin !== "https://branditscan.com" || !e.data || e.data.type !== "bs-agency-leak-check:height") return;
document.querySelectorAll("iframe[src^='https://branditscan.com/embed/agency-leak-check']").forEach(function (f) {
if (f.contentWindow === e.source) f.style.height = Math.ceil(e.data.height) + "px";
});
});
</script>
| Parameter | What it does |
|---|---|
stagenames | Comma-separated roster prefill that runs immediately on load, e.g. ?stagenames=jane,ava,mia — up to 10 models per scan. Results are cached per name, so repeat loads are instant. |
aff | Your BranditScan affiliate slug. Signups from the widget are credited to you — same 10%-for-life program as the Leak Check Widget above. |
rail | Pins the side visual: odometer (money counter — the default here), sweep, cases or loss. |
border | border=0 turns the animated rainbow shell border off (on by default). |
blur | blur=0 renders result images unblurred by default (NSFW-blurred with click-to-reveal out of the box). |
branding | branding=0 hides the BranditScan endnote for white-label embeds. |
w | Max-width cap in px (400–1400) for standalone previews — real embeds size via the iframe. |
postMessage API
Same contract as the single-name widget, in its own namespace — auto-size the iframe, push a roster in from your own UI, and read the aggregate result back:
// OUT — sent by the widget on every layout change (auto-height):
// { "type": "bs-agency-leak-check:height", "height": 1240 }
// OUT — sent when the roster scan completes:
// { "type": "bs-agency-leak-check:result",
// "models": [{ "name", "standing", "piratePct", "pirates" }],
// "atRisk": 3, "clean": 1, "protected": 0, "failed": 0, "total": 4,
// "avgPct": 24.6, "estimatedYearlyLoss": 54000, "domains": ["fapello.com"] }
// IN — push a roster in and run it from your own page:
var frame = document.querySelector("iframe[src*='/embed/agency-leak-check']");
frame.contentWindow.postMessage(
{ type: "bs-agency-leak-check:scan", stagenames: ["jane doe", "ava belle"] },
"https://branditscan.com"
);
?skin= param away: hand us your design tokens and we build a skin that disappears into your product, exactly like our platform-branded takedown widgets. Ask for a skin — or go white-label today with ?branding=0.
Live demo — embedded on your site
This is the real widget, live on this page — add a few stage names, or hit Run sample roster to watch it scan a whole roster end-to-end (uses the widget's postMessage API).
Self Submissions Widget
Unlimited takedowns — embedded in your product
- Per-platform enablement — your embed, tenancy and limits are set up with you, typically within a few days: request it with your production domain and your local dev hosts (localhost, *.test) so it renders in your dev environment too.
- Any depth you want — from the drop-in widget to a fully custom build in your design (like Takedown Labs below).
Own a platform? Give your entire user base unlimited self-submitted takedowns — free, globally, as your feature. Your users paste leak links right inside your product, we take them down, and every link's state updates as it moves through removal. The single most requested tool in the creator industry, shipped plug-and-play.
Ship it as simple or as advanced as you want: drop the ready-made widget in with one snippet (like the Leak Check widget above), or go fully custom — the surface is white-label-friendly and we match your UI/UX and design language so it feels native to your product. Either way there's no per-submission cost to you or your users, and under the hood every submission runs through the same pipeline our own creators use: validation, per-site grouping, DMCA notices, escalations, and Google delisting.
How it works
What the widget handles — and what stays in BranditScan
The widget files takedowns for standard web-page links — the pirate tubes, forums, blogs and file pages that make up the bulk of leaks. The in-app Self Submission's special-case machinery is deliberately not embedded; when a creator pastes one of these, the widget explains why and points them to the full BranditScan app (your embed doubles as a conversion surface):
instagram.com · x.com / twitter.com · facebook.comImpersonation (catfish) reports & social takedowns — need identity verification and the catfish review pipelineshare.google · google.com/search · /url · /imgresGoogle links aren't hosting pages — the app expands them to the real page automaticallybit.ly · goo.gl · t.co · tinyurl.com · fb.me · ig.me · m.meShorteners get expanded before filing — an app-side stepescalations & re-reviewsDuplicate escalation, support flags and manual review flows live in the appCreators see the alert both while pasting and in the submission result ("Only available in BranditScan"), with a signup link — the same pattern the in-app flow uses for platform notices like TikTok.
Live integration — Takedown Labs on YourVids
A real partner build on this surface, fully customized to YourVids' own design — creators submit stolen-content links, takedowns run, and every request tracks its removals live:
Embed — two steps
Your backend signs a short-lived token per page view with your existing HMAC signing secret (issued with your credentials), binding the widget session to one of your users — no other site can load it, and nobody but that user can see their data. Optional stagename / originals claims prefill their one-time setup:
const crypto = require("crypto");
const payload = Buffer.from(JSON.stringify({
v: 1,
pid: YOUR_PLATFORM_ID, // issued with your credentials
uid: user.id, // YOUR user's id — any stable string
name: user.displayName, // optional
stagename: user.stageName, // optional prefill
originals: [user.profileUrl], // optional prefill (their official pages)
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 86400 // 24h — up to 7 days
})).toString("base64url");
const token = payload + "." + crypto
.createHmac("sha256", process.env.BS_SIGNING_SECRET)
.update(payload)
.digest("hex");
$payload = rtrim(strtr(base64_encode(json_encode([
'v' => 1,
'pid' => YOUR_PLATFORM_ID, // issued with your credentials
'uid' => (string) $user->id, // YOUR user's id — any stable string
'name' => $user->display_name, // optional
'stagename' => $user->stage_name, // optional prefill
'originals' => [$user->profile_url],// optional prefill (their official pages)
'iat' => time(),
'exp' => time() + 86400, // 24h — up to 7 days
])), '+/', '-_'), '=');
$token = $payload.'.'.hash_hmac('sha256', $payload, env('BS_SIGNING_SECRET'));
<iframe src="https://branditscan.com/embed/takedowns?t=${token}"
title="Takedowns — powered by BranditScan"
style="display:block;width:100%;max-width:960px;margin:0 auto;height:520px;border:0;border-radius:24px;background:#fff url(https://branditscan.com/front/lp/assets/images/leak-widget-spinner.svg) no-repeat center 140px;"
scrolling="no" loading="lazy"></iframe>
<script>
window.addEventListener("message", (e) => {
if (e.data && e.data.type === "bs-takedowns:height")
document.querySelector("iframe[src*='/embed/takedowns']").style.height = Math.ceil(e.data.height) + "px";
});
</script>
Only domains you register with us can frame the widget (browser-enforced), tokens expire on their own, and suspending a platform cuts every embed instantly. Pairs naturally with the Platform API (accounts, scans, results in your UI) and SSO — but it also works standalone: the widget alone is enough to put takedowns in your product.
Make it yours — theming & white-label
The widget is built to disappear into your product. Every platform gets its own theme, the BranditScan branding is optional, and if theme variables aren't enough we design it with you:
accent · background · radius · font · your logo & labelConfigured per platform — the widget renders in your colors, type and shape out of the boxyour UI/UX & design, 1:1We can make it match your UI/UX & design exactly — or build a fully custom version, like Takedown Labs above| Parameter | What it does |
|---|---|
branding | branding=0 removes the BranditScan logo and text entirely — the widget runs white-label inside your product (branding shown by default). |
border | border=1 adds the animated rainbow shell border — the Leak Check treatment (off by default). |
logo | URL of your logo, e.g. logo=https://yoursite.com/logo.png — shown in the widget header (transparent PNG works best; https only, wins over the per-platform theme logo). |
celebrate | celebrate=1 adds the celebration reel — a slow vertical rotation of the creator's real removal screenshots (source removals first, then delistings, each with the site's icon) behind a big green count of everything removed & delisted (off by default; appears once the creator has removals). |
blur | blur=0 unblurs the NSFW image thumbnails (the funnel's stolen-image tiles and the nested leak-check results) — blurred by default. |
funnel | How the built-in leak-check funnel presents itself: simple (default — the clean card), pulse (primary CTA with a live-dot and a periodic sheen), or one of the personalized variants that pre-run the scan in the background and rewrite the card from the result: teaser ("31% of your search traffic goes to leak sites" + the pirate sites' icons), revenue (the upside framing — "Boost your revenue by +31%", green with a gold coin), loss (the money framing — "creators lose on average $18,000 a year to piracy", gold figure), evidence (4 of the creator's actual stolen images, blurred with red rings, straight from Google Images), or wall (the full grid — up to 50 confirmed pirated images, each title-matched to the creator on a confirmed pirate site). Pre-run scans are cached per stage name — one scan per creator. funnel=off removes the leak-check card entirely. |
POST /users, same external id as the token's uid), the widget automatically shows an "Open my BranditScan" button — one click signs the member into their own account in a new tab, reusing the very token that authenticated the iframe. Not doing SSO? Skip this — nothing changes.
Live demo — sandbox
This is the real widget in sandbox mode — fixture data, nothing is filed. Paste any links and submit to see the full flow, exactly as your users would.
Request the Self Submissions WidgetSSO API
Sign your users into BranditScan in one tap
- A Platform API partnership — SSO is enabled per platform as part of it: request the integration or book a call.
Use case: your users tap "Open BranditScan" inside your app, site, or Telegram bot — and land in their BranditScan dashboard already signed in. No passwords, no onboarding friction, no support tickets.
SSO is part of the Platform API: you mint a one-time, short-lived token for a user your platform created, then send the user to the returned URL. The consume page is crawler-proof — link previews and bots that prefetch URLs can't burn the token.
/api/platform/sso/tokenMint a one-time SSO token for one of your users/sso/platform/{token}Browser URL — signs the user in (dashboard, or the onboarding wizard until it's completed)How to wire it — four steps
- Once per user — create their BranditScan account. SSO only works for users your platform created via
POST /api/platform/users. Use your own user id asexternal_id— that's the reference you'll mint tokens with forever after. The call is idempotent, so it's safe to run it right before every mint. - On every "Open BranditScan" click — mint a token from your backend.
POST /api/platform/sso/tokenwith{"reference": "<your external_id>"}, signed like every Platform API call (the token endpoint is server-to-server — your signing secret never touches the browser). Mint fresh per click; never pre-mint, never cache, never put the URL in emails or chat messages. - Send the user's browser to
redirect_url— as a top-level navigation:window.location = urlor a new tab (window.open/target="_blank"). Never inside an iframe — third-party cookie rules break the session there. The user sees a split-second interstitial, then they're signed in on branditscan.com. (The interstitial is what makes links crawler-proof: a bot's GET can't consume the token; only the browser's auto-submit does.) - Where they land: platforms on wizard onboarding → straight onto the onboarding wizard's stage-name step, prefilled from the name you sent (then the live first scan and the plan offer; returners resume at whichever step they left). Already-onboarded users → their dashboard.
uid / external_id), and the Leak Check Widget does the same when you pass that token as &t=. Both reuse the widget token as proof — you don't call the mint endpoint at all for in-widget sign-ins.
Step 2 in practice — mint the token
curl -X POST https://branditscan.com/api/platform/sso/token \
-H "Authorization: Bearer bsp_12_XXXXXXXXXXXXXXXXXXXX" \
-H "X-Platform-Timestamp: 1767225600" \
-H "X-Platform-Signature: 3f2a9c1e8b..." \
-H "Content-Type: application/json" \
-d '{"reference": "tg_482913"}'
{
"redirect_url": "https://branditscan.com/sso/platform/hnJdQ3...64-char-token...kQ",
"expires_at": "2026-07-14T18:08:21+00:00",
"expires_in": 300
}
The whole button, end to end
// BACKEND — one route your button calls:
app.post('/integrations/branditscan/open', async (req, res) => {
const reference = String(req.user.id);
// idempotent: 201 first time, 200 after; 409 = email already on BranditScan
const created = await bsApi('POST', '/users', {
email: req.user.email,
name: req.user.displayName,
stagenames: [req.user.stagename],
external_id: reference,
});
if (created.status === 409) return res.status(409).json({ error: 'existing_account' });
const sso = await bsApi('POST', '/sso/token', { reference });
return res.json({ redirect_url: sso.json.redirect_url });
});
// FRONTEND — the "Open BranditScan" button:
const { redirect_url } = await fetch('/integrations/branditscan/open', { method: 'POST' })
.then(r => r.json());
window.open(redirect_url, '_blank'); // or: window.location = redirect_url
Error semantics
unknown referenceThe user was never created by your platform — run step 1 firstrefusedSSO not enabled for your platform, or the target is a privileged accountused / >5 min oldThe user sees a friendly "link expired" login page — just mint a fresh one on the next click- One-time use, 5-minute TTL — mint a fresh token for every tap; never cache or reuse URLs.
- Tenancy-scoped — a platform can only mint SSO for users it created. Admin and staff accounts can never be signed in via SSO.
- Signed requests — same authentication scheme as the rest of the Platform API.
Network Manager API
Roster-wide protection reports for agencies & studios
- A network manager (agency / studio) account on BranditScan plus an API token — ask and we'll switch it on for your account.
Use case: you run an agency or studio with a roster of creators on BranditScan — and you want their protection numbers inside your own dashboards, reporting, and client decks instead of logging in per account.
Roster-wide reporting over every creator your network manager account oversees: links found, takedowns filed, removals, and per-domain breakdowns — filterable by membership tier, domain, and date range.
/api/v2/manager/users/reportProtection report for every managed creator/api/v2/manager/users/cachePre-warm report caches for your roster/api/manager/takedownFile takedowns on behalf of a managed creator| Parameter | Description |
|---|---|
membership | Filter the roster: premium, basic, or unverified. Default premium. |
domain | Scope the report to one pirate domain, e.g. fapello.com. |
from_date / to_date | Report window, Y-m-d. Both required when either is set. |
Sample request
curl -X POST https://branditscan.com/api/v2/manager/users/report \
-H "Authorization: Bearer $MANAGER_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"membership": "premium", "from_date": "2026-06-01", "to_date": "2026-06-30"}'
Platform API — scans & results
Launch scans for your users, serve their piracy results in your product
- A partnership — platform credentials, quotas, SSO and your commission rate are scoped per partner: pitch us your platform or book a call. Commission details live on the Affiliate Program page.
Own a platform? Put real leak scans and live piracy results inside your product — your platform creates BranditScan accounts for its users, launches scans on demand, and renders the findings natively in your own UI. Your users see their leaks where they already are: on your platform. And you earn a commission on every subscription it produces.
The Platform API is a multi-tenant partner surface: create BranditScan accounts for your users, launch scans, poll completion, pull infringements and per-site rollups into your own UI, and sign users straight into their dashboard via SSO. Everything is tenancy-scoped — your platform only ever sees the users it created. Looking for unlimited self-submitted takedowns instead? That's the Self Submissions Widget.
Endpoints
/api/platform/usersCreate a BranditScan user (1–3 stagenames)/api/platform/users/syncBulk membership status for up to 200 of your users/api/platform/users/lookupMass existence check by email or stagename/api/platform/scansLaunch a scan for one of your users/api/platform/scans/{id}Poll scan progress + summary/api/platform/users/{ref}/infringementsPaginated infringing links/api/platform/users/{ref}/branditsPer-domain rollup with piracy intel/api/platform/traffic-checkRun a leak check for any stagenameAuthentication
Every request carries three headers: your bearer key, a unix timestamp (±300s of server time), and an HMAC-SHA256 signature of "{timestamp}.{rawBody}" keyed by your signing secret. An IP allowlist and per-platform rate limits apply on top.
const crypto = require("crypto");
const timestamp = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify(payload); // exact raw body you will send
const signature = crypto
.createHmac("sha256", process.env.BS_SIGNING_SECRET)
.update(timestamp + "." + body)
.digest("hex");
// Headers:
// Authorization: Bearer bsp_12_XXXXXXXXXXXXXXXXXXXX
// X-Platform-Timestamp: timestamp
// X-Platform-Signature: signature
1 — Create a user
Two onboarding modes, set per platform. Provisioned — the account is created ready to scan with the given stagenames (headless integrations, bots). Wizard onboarding — a bare OAuth-style registration: email pre-verified, the display name from your platform, and the stage-name step prefilled; when the creator SSOs in they walk through the standard BranditScan onboarding (scan → plan) themselves. Signups are attributed to your affiliate account either way.
curl -X POST https://branditscan.com/api/platform/users \
-H "Authorization: Bearer bsp_12_XXXXXXXXXXXXXXXXXXXX" \
-H "X-Platform-Timestamp: 1767225600" \
-H "X-Platform-Signature: 3f2a9c1e8b..." \
-H "Content-Type: application/json" \
-d '{"email": "creator@example.com", "name": "Jane Doe", "stagenames": ["jane doe"], "external_id": "tg_482913"}'
{
"user": {
"bs_user_id": 38412,
"external_id": "tg_482913",
"email": "creator@example.com",
"is_premium": false,
"membership": 0
}
}
- Existing emails are rejected (409) — a platform can never claim an account it didn't create.
- Idempotent — re-sending the same external_id returns the existing user instead of erroring.
2 — Launch a scan, poll until complete
curl -X POST https://branditscan.com/api/platform/scans \
-H "Authorization: Bearer bsp_12_XXXXXXXXXXXXXXXXXXXX" \
-H "X-Platform-Timestamp: 1767225600" \
-H "X-Platform-Signature: 9d41be07ac..." \
-H "Content-Type: application/json" \
-d '{"reference": "tg_482913"}'
{
"scan": {
"id": 512,
"reference": "tg_482913",
"bs_user_id": 38412,
"queue": "first-search",
"progress": 100,
"completed": true,
"created_at": "2026-07-14T18:03:21+00:00",
"completed_at": "2026-07-14T19:41:05+00:00",
"summary": {
"total_links": 1204,
"total_views": 8125940,
"total_loss": 24377,
"total_domains": 87,
"top_websites": [
{ "domain": "fapello.com", "links_count": 214 },
{ "domain": "leakedzone.com", "links_count": 168 }
]
}
}
}
3 — Pull the findings into your UI
{
"data": [
{
"id": 981220431,
"url": "https://fapello.com/jane-doe/",
"title": "Jane Doe Nude Leaks",
"website": "fapello.com",
"views": 48210,
"states": ["Active"],
"in_dmca": true,
"found_at": "2026-07-14T19:22:41+00:00"
}
],
"pagination": { "page": 1, "per_page": 25, "total": 1204, "last_page": 49 }
}
Finish the loop with SSO: one tap in your product and the creator is inside their BranditScan dashboard, where takedowns run 24/7.
Pitch us your platform Affiliate ProgramBook an intro call
30 minutes — scope your integration live with the founding team
Faster than email ping-pong: grab a slot, tell us what you're building, and we'll map the right APIs, quotas, and commercials with you on the call — credentials usually follow within a working day.




ModelPlug