Docs
Ctrl+K Rechercher Alt+[Alt+] Guides
Obtenir une clé API

API

Marques et suivi des marques

Track Meta pages, pull brand analytics, and manage digest notification prefs — all with Clé X-API. MCP equivalents: list_tracked_brands, track_brand, analyze_tracked_brand.

List tracked brands

OBTENIR/api/v1/marques

Paginated list of tracked brands for the API key owner.

Send Clé X-API on every request.

Query parameters

  • trierstring

    Sort field.

    Default: date_addedValues: date_added nom active_ads new_ads growth traffic chiffre d'affaires
  • dirstring

    Sens de tri.

    Default: descValues: asc desc
  • rechercherstring

    Match on brand name or page id.

  • board_idstring

    Only brands on that saved board.

  • pageinteger

    1-based page.

    Default: 1
  • limiteinteger

    Page size; max 50.

    Default: 10
  • litestring

    Set to 1 for lighter enrichment.

  • filter_active_adsstring
  • filter_trafficstring
  • filter_revenuestring
  • revenue_periodstring
    Default: 30dValues: 1d 30d
Demande
curl -sS \
  -H "X-API-Key: $WH_API_KEY" \
  "{origin}/api/v1/brands?sort=date_added&dir=desc&search=string&board_id=string&page=1&limit=10&lite=string&filter_active_ads=string&filter_traffic=string&filter_revenue=string&revenue_period=30d"
const res = await fetch(`${ORIGIN}/api/v1/brands?sort=date_added&dir=desc&search=string&board_id=string&page=1&limit=10&lite=string&filter_active_ads=string&filter_traffic=string&filter_revenue=string&revenue_period=30d`, {
  method: 'GET',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
  },
});
const data = await res.json();
import os, requests

res = requests.get(
    f"{ORIGIN}/api/v1/brands?sort=date_added&dir=desc&search=string&board_id=string&page=1&limit=10&lite=string&filter_active_ads=string&filter_traffic=string&filter_revenue=string&revenue_period=30d",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
)
data = res.json()
Response
{
    "brands": [
        {
            "id": "108897621643793",
            "name": "Allbirds",
            "logo_url": "https://…",
            "page_url": "https://www.facebook.com/108897621643793",
            "status": "active",
            "total_ads": 412,
            "active_ads_on_page": 142,
            "formats": {
                "videos": 84,
                "images": 52,
                "dco": 4,
                "carousels": 2
            },
            "new_ads_count": 18,
            "new_ads_change": 0.14,
            "traffic": 412000,
            "traffic_change": 0.08,
            "commerce": null,
            "added_at": "April 12, 2024",
            "primary_domain": "allbirds.com",
            "source_shopid": "allbirds",
            "details_url": "/store/allbirds/meta-ads"
        }
    ],
    "total": 37,
    "page": 1,
    "limit": 10,
    "total_pages": 4,
    "brand_request_quota": {
        "used": 2,
        "limit": 30,
        "remaining": 28,
        "month": "2026-08"
    }
}
{
    "success": false,
    "error": "Unauthorized"
}
{
    "success": false,
    "error": "WinningHunter Basic plan or higher required"
}
{
    "success": false,
    "error": "Rate limit exceeded. Max 60 requests per minute."
}

Response is an object with a brands array — not a bare array and not { success, data }.

Brand ads

OBTENIR/api/v1/brands/ads

Paginated Meta ads for a tracked brand page.

Send Clé X-API on every request.

Query parameters

  • idstringrequired

    Facebook page_id from the brands list.

  • pageinteger

    0-based page index.

    Default: 0
  • date_rangestring

    all | live | 7d | 30d | 3m | 6m | custom (with date_from + date_to).

  • date_de_débutstring

    Y-m-d when date_range=custom.

  • date_tostring

    Y-m-d when date_range=custom.

Demande
curl -sS \
  -H "X-API-Key: $WH_API_KEY" \
  "{origin}/api/v1/brands/ads?id=108897621643793&page=0&date_range=string&date_from=string&date_to=string"
const res = await fetch(`${ORIGIN}/api/v1/brands/ads?id=108897621643793&page=0&date_range=string&date_from=string&date_to=string`, {
  method: 'GET',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
  },
});
const data = await res.json();
import os, requests

res = requests.get(
    f"{ORIGIN}/api/v1/brands/ads?id=108897621643793&page=0&date_range=string&date_from=string&date_to=string",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
)
data = res.json()
Response
[
    {
        "productid": "1284756102394857",
        "pageName": "Allbirds",
        "page_id": "108897621643793",
        "caption": "Meet the Tree Runner — carbon neutral comfort.",
        "copy": "Meet the Tree Runner — carbon neutral comfort.",
        "started": "2025-11-02",
        "lastSeen": "2026-03-14",
        "daysrunning": 133,
        "running_days": 133,
        "adscore": "Winning",
        "adscore_reasons": [
            "Ad is running for longer than 7 days"
        ],
        "total_eu_views_30d": 842000,
        "urlStore": "https://allbirds.com/products/mens-tree-runners",
        "saved": false,
        "hidden": false
    }
]
{
    "error": "Page ID is required"
}
{
    "success": false,
    "error": "Unauthorized"
}

Returns a JSON array of processed ad objects (same Utils::process_ads shape as Meta ad library / Magic AI) — not { success, data }. Use daysrunning / pageName (and productid). There is no bare id ou platform field on these cards.

Track / untrack

PUBLICATION/api/v1/brands/follow

Add a Meta page to Brand Tracker from a Facebook Ad Library URL.

Send Clé X-API on every request.

Body parameters

  • urlstringrequired
Demande
curl -sS \
  -X POST \
  -H "X-API-Key: $WH_API_KEY" \
  -H "Content-Type: application/json" \
  "{origin}/api/v1/brands/follow" \
  -d '{"url":"https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&view_all_page_id=108897621643793"}'
const res = await fetch(`${ORIGIN}/api/v1/brands/follow`, {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&view_all_page_id=108897621643793"
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    f"{ORIGIN}/api/v1/brands/follow",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
    json={
        "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&view_all_page_id=108897621643793"
    },
)
data = res.json()
Response
{
    "success": true,
    "brand": {
        "id": "108897621643793",
        "name": "Allbirds",
        "logo_url": "https://…",
        "status": "active",
        "formats": {
            "videos": 0,
            "images": 0,
            "dco": 0,
            "carousels": 0
        }
    },
    "has_data": true,
    "details_url": "/store/allbirds/meta-ads",
    "amount": 38,
    "max_allowed": 50
}
{
    "success": false,
    "error": "Invalid URL",
    "message": "Please enter a valid Facebook Ad Library URL with a view_all_page_id parameter."
}
{
    "success": false,
    "error": "Unauthorized"
}
{
    "success": false,
    "error": "Brand limit reached",
    "limit": "reached",
    "message": "You have reached your plan limit of 50 competitors tracked. Upgrade to follow more."
}
PUBLICATION/api/v1/brands/unfollow

Remove one or more tracked brands.

Send Clé X-API on every request.

Body parameters

  • page_idstring
  • page_idsarray

    Array of page ids.

Demande
curl -sS \
  -X POST \
  -H "X-API-Key: $WH_API_KEY" \
  -H "Content-Type: application/json" \
  "{origin}/api/v1/brands/unfollow" \
  -d '{"page_id":"string","page_ids":[]}'
const res = await fetch(`${ORIGIN}/api/v1/brands/unfollow`, {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "page_id": "string",
      "page_ids": []
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    f"{ORIGIN}/api/v1/brands/unfollow",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
    json={
        "page_id": "string",
        "page_ids": []
    },
)
data = res.json()
Response
{
    "success": true,
    "amount": 37,
    "max_allowed": 50,
    "removed": 1
}
{
    "success": false,
    "error": "Invalid page id"
}
{
    "success": false,
    "error": "Unauthorized"
}

Also available: POST /api/v1/brands/follow-by-domain (body: { "domain": "allbirds.com" }), POST /api/v1/brands/request (request a brand not yet in the index).

If the page is already tracked, follow returns { "success": true, "already_tracked": true, "has_data": bool, "details_url": "…", "message": "Brand is already in your tracker." } instead of the brand object.

Brand analytics tabs

All require id (page_id) unless noted. GET /api/v1/brands/fetch-status is the exception — it requires page_id (not id). Optional date_range / date_de_début / date_to — same rules as Plages horaires.

Method Chemin Objectif
OBTENIR /api/v1/brands/amount-tracked Tracked count + plan cap — { "amount": int, "max_allowed": int }
OBTENIR /api/v1/brands/overview-cards Summary KPI cards
OBTENIR /api/v1/brands/top-ads Top ads (platform, trier query params)
OBTENIR /api/v1/brands/top-ads-platform-counts Ad counts by platform
OBTENIR /api/v1/brands/ad-rank-leaderboard Rank leaderboard
OBTENIR /api/v1/brands/ads-launched Ads launched over time
OBTENIR /api/v1/brands/live-ads-over-time Live ad count series
OBTENIR /api/v1/brands/first-ad-date First seen ad date
OBTENIR /api/v1/brands/ad-copies Ad copy snippets
OBTENIR /api/v1/brands/ad-headlines Headlines
OBTENIR /api/v1/brands/ad-hooks Hooks
OBTENIR /api/v1/brands/commerce Commerce signals
OBTENIR /api/v1/brands/ads-by-ids Batch fetch by ad ids
OBTENIR /api/v1/brands/personas Persona breakdown
OBTENIR /api/v1/brands/themes Creative themes
OBTENIR /api/v1/brands/angles Angles
OBTENIR /api/v1/brands/desires Désirs
OBTENIR /api/v1/brands/emotions Émotions
OBTENIR /api/v1/brands/awareness-stages Awareness stages
OBTENIR /api/v1/brands/funnel-stages Funnel stages
OBTENIR /api/v1/brands/usps arguments clés de vente
OBTENIR /api/v1/brands/partner-pages Partner pages
OBTENIR /api/v1/brands/partnership-ads Partnership ads
OBTENIR /api/v1/brands/associated-domains Domaines associés
OBTENIR /api/v1/brands/landing-pages Landing pages
OBTENIR /api/v1/brands/fetch-status Data readiness — query page_id{ success, has_data, summary }

Each costs 1 API credit and returns the same JSON as the dashboard tab.

OBTENIR/api/v1/brands/overview-cards

Summary KPI cards (personas, themes, angles, desires, emotions, USPs).

Send Clé X-API on every request.

Query parameters

  • idstringrequired

    Facebook page_id.

Demande
curl -sS \
  -H "X-API-Key: $WH_API_KEY" \
  "{origin}/api/v1/brands/overview-cards?id=string"
const res = await fetch(`${ORIGIN}/api/v1/brands/overview-cards?id=string`, {
  method: 'GET',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
  },
});
const data = await res.json();
import os, requests

res = requests.get(
    f"{ORIGIN}/api/v1/brands/overview-cards?id=string",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
)
data = res.json()
Response
{
    "success": true,
    "personas": [
        {
            "tag": "Health-conscious millennial",
            "count": 42
        }
    ],
    "themes": [
        {
            "tag": "Sustainability",
            "count": 28
        }
    ],
    "angles": [
        {
            "tag": "Comfort-first",
            "count": 19
        }
    ],
    "desires": [
        {
            "tag": "Feel good",
            "count": 15
        }
    ],
    "emotions": [
        {
            "tag": "Trust",
            "count": 12
        }
    ],
    "usps": [
        {
            "tag": "Carbon neutral",
            "count": 9
        }
    ],
    "personas_fetching": false,
    "themes_fetching": false,
    "angles_fetching": false,
    "desires_fetching": false,
    "emotions_fetching": false,
    "usps_fetching": false
}
OBTENIR/api/v1/brands/ad-copies

Paginated ad copy snippets for insight tab.

Send Clé X-API on every request.

Query parameters

  • idstringrequired
  • pageinteger
    Default: 1
  • trierstring
    Default: Utilisation
  • rechercherstring
Demande
curl -sS \
  -H "X-API-Key: $WH_API_KEY" \
  "{origin}/api/v1/brands/ad-copies?id=string&page=1&sort=Usage&search=string"
const res = await fetch(`${ORIGIN}/api/v1/brands/ad-copies?id=string&page=1&sort=Usage&search=string`, {
  method: 'GET',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
  },
});
const data = await res.json();
import os, requests

res = requests.get(
    f"{ORIGIN}/api/v1/brands/ad-copies?id=string&page=1&sort=Usage&search=string",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
)
data = res.json()
Response
{
    "success": true,
    "data": [
        {
            "copy": "Meet the Tree Runner — carbon neutral comfort.",
            "count": 14,
            "ad_ids": [
                "1284756102394857"
            ],
            "max_days_running": 133,
            "max_days_running_ad_id": "1284756102394857"
        }
    ],
    "has_more": true
}

Other insight tabs (ad-headlines, hooks, personas, …) follow the same { success, data[], has_more } pattern unless noted in the dashboard.

Brand boards & folders

Organize tracked brands into folders and boards — same as the Brand Tracker sidebar. All routes cost 1 API credit and accept JSON body or form fields (query params are merged for GET).

Method Chemin Objectif
OBTENIR /api/v1/brands/folders-with-boards Nested folders + boards tree
PUBLICATION /api/v1/brands/create-folder Create folder (nom) → { success, folder_id, name }
PUBLICATION /api/v1/brands/rename-folder Rename folder (id, nom)
PUBLICATION /api/v1/brands/delete-folder Delete folder (id)
PUBLICATION /api/v1/brands/create-board Create board (folder_id, nom) → { success, board_id, name }
PUBLICATION /api/v1/brands/rename-board Rename board (id, nom)
PUBLICATION /api/v1/brands/delete-board Delete board (id)
PUBLICATION /api/v1/brands/add-to-board Add brand to board (board_id, brand id fields)
PUBLICATION /api/v1/brands/remove-from-board Remove brand from board
PUBLICATION /api/v1/brands/generate-shareable-board-link Share link → { success, url, token }

POST bodies may be form fields or JSON (JSON is merged into $_POST on /api/v1/brands/*). Board list is a bare array: [{ "id", "name", "created_at", "boards": [{ "id", "name", "brands_count", "brands": [] }] }].

Brand digest notifications

OBTENIR/api/v1/brands/notifications/prefs

Brand digest email preferences and per-brand toggles.

Send Clé X-API on every request.
Demande
curl -sS \
  -H "X-API-Key: $WH_API_KEY" \
  "{origin}/api/v1/brands/notifications/prefs"
const res = await fetch(`${ORIGIN}/api/v1/brands/notifications/prefs`, {
  method: 'GET',
  headers: {
    'X-API-Key': process.env.WH_API_KEY,
  },
});
const data = await res.json();
import os, requests

res = requests.get(
    f"{ORIGIN}/api/v1/brands/notifications/prefs",
    headers={"X-API-Key": os.environ["WH_API_KEY"]},
)
data = res.json()
Response
{
    "success": true,
    "prefs": {
        "auto_enable_new_brands": true,
        "channels": {
            "email": true,
            "in_app": false
        },
        "digest": {
            "timezone": "UTC",
            "daily": {
                "enabled": false,
                "time": "09:00"
            },
            "weekly": {
                "enabled": false,
                "time": "09:00",
                "weekday": 1
            },
            "monthly": {
                "enabled": false,
                "time": "09:00",
                "monthday": 1
            }
        },
        "events": {
            "new_meta_ads": {
                "in_digest": true
            },
            "new_emails": {
                "in_digest": true
            },
            "new_products": {
                "in_digest": true
            },
            "active_ads_change": {
                "in_digest": true
            },
            "spend_eu": {
                "in_digest": true,
                "threshold_pct": 50
            },
            "ad_rank": {
                "in_digest": true,
                "top_n": 5
            }
        },
        "brands": {
            "108897621643793": {
                "enabled": true
            }
        }
    },
    "brands": [
        {
            "id": "108897621643793",
            "name": "Allbirds",
            "logo_url": "https://…",
            "enabled": true
        }
    ],
    "enabled_count": 12,
    "total_count": 37
}
{
    "success": false,
    "error": "Unauthorized"
}

POST /api/v1/brands/notifications/prefs/save — JSON body with nested channels, digest, events, auto_enable_new_brands, and/or per-brand toggles via brands map or brand_updates. Returns { "success": true, "prefs": { …full prefs object… } }.

Product inbox notifications (/api/v1/notifications/*) are documented on Notifications.

Date range on insight tabs

date_range Signification
(omission) ou tout No date filter
en direct Last seen in the last 4 days (dernière mise à jour)
7d, 30d, 3m, 6m Rolling start-date cutoff
personnalisé Requires date_de_début + date_to (J-m-a)